mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
870
Commits
0.9.9-beta1
...
1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6692276472 | ||
|
|
81c09a9c9c | ||
|
|
6a0a367ec3 | ||
|
|
bdf533d62b | ||
|
|
1aba0bc26c | ||
|
|
aac6e9a365 | ||
|
|
9da732d96c | ||
|
|
328ba43ed2 | ||
|
|
62d3253b02 | ||
|
|
e5ba01e707 | ||
|
|
82c25f7f8c | ||
|
|
8791866ea0 | ||
|
|
8f10b8fece | ||
|
|
0d28d210d4 | ||
|
|
2368a5a050 | ||
|
|
74a9b1b41d | ||
|
|
672c49e8eb | ||
|
|
225db32636 | ||
|
|
01541e4a50 | ||
|
|
357e260b45 | ||
|
|
a2513b1851 | ||
|
|
bbe8604054 | ||
|
|
58a33de7f7 | ||
|
|
ab7abc6a48 | ||
|
|
4986bdf202 | ||
|
|
11aaddac98 | ||
|
|
da9b2b4378 | ||
|
|
9771a98bc6 | ||
|
|
033ee5f4e9 | ||
|
|
1383163627 | ||
|
|
1d31b35c4f | ||
|
|
7b2cc757b2 | ||
|
|
68cddd1c2e | ||
|
|
b2a9fbbc5c | ||
|
|
0fcb13b9f1 | ||
|
|
938a22ce2e | ||
|
|
2df5dbfe52 | ||
|
|
feed0d0faa | ||
|
|
c8373d20a9 | ||
|
|
170267a04a | ||
|
|
bd5969db67 | ||
|
|
02256c013c | ||
|
|
89be9a0d4a | ||
|
|
4e57a6e145 | ||
|
|
784434ef3e | ||
|
|
91273b2301 | ||
|
|
2bcc85a99f | ||
|
|
b7e6da3392 | ||
|
|
d934270a27 | ||
|
|
ed5a268e1f | ||
|
|
95beaa0a86 | ||
|
|
0d3bf93c76 | ||
|
|
50fb43066a | ||
|
|
c33ec8ff56 | ||
|
|
e6afeec8af | ||
|
|
57b9bdb958 | ||
|
|
315bcb72c9 | ||
|
|
6b2460c02f | ||
|
|
35bc999a59 | ||
|
|
f00ad75e45 | ||
|
|
6bfe8e5b41 | ||
|
|
d7e8fd7d06 | ||
|
|
949a0c35d5 | ||
|
|
d193d5572f | ||
|
|
f79f7e44a7 | ||
|
|
26db55aafd | ||
|
|
9d405c6cb2 | ||
|
|
cceee511f2 | ||
|
|
e2024ed2fd | ||
|
|
add7e2ee0e | ||
|
|
0458aa8eb4 | ||
|
|
9ff6be783a | ||
|
|
14c558559b | ||
|
|
92c5dcb6f2 | ||
|
|
ae31f349f7 | ||
|
|
ce2846d04f | ||
|
|
7a6c9a5fe4 | ||
|
|
43c258ad48 | ||
|
|
8ba032adb2 | ||
|
|
1a61dfd4e0 | ||
|
|
8e150e77a8 | ||
|
|
729fa753fa | ||
|
|
bf6c552189 | ||
|
|
e9dc987a95 | ||
|
|
35d9a39100 | ||
|
|
a864c8d6ed | ||
|
|
c2df8a099e | ||
|
|
878e9cb9ba | ||
|
|
3612ea2186 | ||
|
|
81f0f93d96 | ||
|
|
c2d7b65145 | ||
|
|
6274e82cea | ||
|
|
66655c9429 | ||
|
|
f47c8553d5 | ||
|
|
f2802d3332 | ||
|
|
1a173c849f | ||
|
|
57d4cd9fc9 | ||
|
|
f6b9345716 | ||
|
|
792cd01320 | ||
|
|
03bc7d0399 | ||
|
|
ed8f0812d7 | ||
|
|
196dc45d0b | ||
|
|
f8ff906d1b | ||
|
|
bbf1b0eda5 | ||
|
|
6f811a4899 | ||
|
|
c66957d685 | ||
|
|
282b2d5ace | ||
|
|
6a73e3ae05 | ||
|
|
5856d410fd | ||
|
|
08d9de54f0 | ||
|
|
af1f98131a | ||
|
|
9cef49ec57 | ||
|
|
d60c6d50ec | ||
|
|
f3fdec2739 | ||
|
|
1a20f57b73 | ||
|
|
0fc74dac4d | ||
|
|
4117dd91fc | ||
|
|
508ca0df39 | ||
|
|
a50e356beb | ||
|
|
a0b7237083 | ||
|
|
08afa73e69 | ||
|
|
b386317921 | ||
|
|
2043127f22 | ||
|
|
c297a9415b | ||
|
|
f9f9f25a01 | ||
|
|
9001af1beb | ||
|
|
4b03f17186 | ||
|
|
3dbab36b91 | ||
|
|
056c890845 | ||
|
|
4f43cd74ad | ||
|
|
6585b7b13d | ||
|
|
e55048b574 | ||
|
|
570dcde654 | ||
|
|
3cb16ee29b | ||
|
|
bb453da5b5 | ||
|
|
1a93b68664 | ||
|
|
2ce2494a50 | ||
|
|
0a1e451289 | ||
|
|
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 |
@@ -28,3 +28,26 @@ e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
|
||||
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
|
||||
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
|
||||
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
|
||||
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
|
||||
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
|
||||
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
|
||||
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
|
||||
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
|
||||
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
|
||||
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
|
||||
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
|
||||
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
|
||||
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
|
||||
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
|
||||
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
|
||||
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
|
||||
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
|
||||
3c70927335856883283fe4db448e092cecc0ccdb 1.0
|
||||
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
|
||||
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
|
||||
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
|
||||
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
|
||||
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
|
||||
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
|
||||
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
|
||||
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
|
||||
|
||||
@@ -12,3 +12,9 @@ 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,109 @@
|
||||
*** april 2012 ***
|
||||
|
||||
* 1.2 [20120430]
|
||||
|
||||
- PyPy support
|
||||
- Improved gevent support with threads
|
||||
- Python auto-reload subsystem
|
||||
- added --spooler-max-tasks
|
||||
- pthread robust mutexes support in Linux and Solaris
|
||||
- posix semaphores support in FreeBSD9
|
||||
- thread-safe ctime() reporting
|
||||
- interval support in cron subsystem
|
||||
- improved syslog support
|
||||
- better management of disconnected clients
|
||||
- static files serving improvements
|
||||
- another set of multithreading optimizations
|
||||
- minor fixes in the Rack plugin
|
||||
- Upstart socket-activation support
|
||||
|
||||
|
||||
*** march 2012 ***
|
||||
|
||||
* 1.1 [20120317]
|
||||
|
||||
- new options parser subsystem
|
||||
- improved php support
|
||||
- multiple spooler with multiprocessing
|
||||
- segmentation fault and floating point exceptions manager
|
||||
- never-swap option
|
||||
- zergpool plugin
|
||||
- perl/psgi multiple interpreters support
|
||||
- deadlock detector
|
||||
- pluggable cheaper algos
|
||||
- new internal routing susbsystem
|
||||
- preliminary support for config logic
|
||||
- log rotation infrastructure
|
||||
- support for paste loggers
|
||||
- threading improvements
|
||||
- plugins can now mapped to specific modifiers
|
||||
- <app> tag is deprecated (use mount option)
|
||||
- report startup time for apps
|
||||
- reintroduced expat support
|
||||
- reintroduced remote spooler plugin
|
||||
- various fastrouter optimizations
|
||||
- added ruby rvm support
|
||||
|
||||
|
||||
*** 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]
|
||||
|
||||
@@ -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
|
||||
+29
-2
@@ -160,20 +160,35 @@ static int uwsgi_map_location(request_rec *r)
|
||||
return DECLINED;
|
||||
}
|
||||
|
||||
static void log_err(const char *file, int line, request_rec *r,
|
||||
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
static void log_err(const char *file, int line, int ami, request_rec *r,
|
||||
apr_status_t status, const char *msg)
|
||||
{
|
||||
ap_log_rerror(file, line, APLOG_MODULE_INDEX, APLOG_ERR, status, r, "uwsgi: %s", msg);
|
||||
#else
|
||||
static void log_err(const char *file, int line, request_rec *r,
|
||||
apr_status_t status, const char *msg)
|
||||
{
|
||||
|
||||
ap_log_rerror(file, line, APLOG_ERR, status, r, "uwsgi: %s", msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void log_debug(const char *file, int line, request_rec *r, const
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
static void log_debug(const char *file, int line, int ami, request_rec *r, const
|
||||
char *msg)
|
||||
{
|
||||
/*
|
||||
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, msg);
|
||||
ap_log_rerror(file, line, APLOG_WARNING, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
*/
|
||||
ap_log_rerror(file, line, APLOG_MODULE_INDEX, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
#else
|
||||
static void log_debug(const char *file, int line, request_rec *r, const
|
||||
char *msg) {
|
||||
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* buffered socket implementation (buckets are overkill) */
|
||||
@@ -412,7 +427,11 @@ send_headers(request_rec *r, struct sockbuff *s)
|
||||
apr_table_t *t;
|
||||
apr_status_t rv = 0;
|
||||
apr_port_t port = 0;
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
GET_PORT(port, r->useragent_addr);
|
||||
#else
|
||||
GET_PORT(port, r->connection->remote_addr);
|
||||
#endif
|
||||
uwsgi_cfg *cfg = our_dconfig(r);
|
||||
|
||||
log_debug(APLOG_MARK,r, "sending headers");
|
||||
@@ -430,7 +449,11 @@ send_headers(request_rec *r, struct sockbuff *s)
|
||||
|
||||
add_header(t, "REQUEST_METHOD", (char *) r->method);
|
||||
add_header(t, "QUERY_STRING", r->args ? r->args : "");
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
add_header(t, "SERVER_SOFTWARE", ap_get_server_description());
|
||||
#else
|
||||
add_header(t, "SERVER_SOFTWARE", ap_get_server_version());
|
||||
#endif
|
||||
add_header(t, "SERVER_ADMIN", r->server->server_admin);
|
||||
add_header(t, "SERVER_NAME", (char *) ap_get_server_name(r));
|
||||
add_header(t, "SERVER_PORT", apr_psprintf(r->pool, "%u",ap_get_server_port(r)));
|
||||
@@ -438,7 +461,11 @@ send_headers(request_rec *r, struct sockbuff *s)
|
||||
add_header(t, "SERVER_PROTOCOL", r->protocol);
|
||||
|
||||
add_header(t, "REQUEST_URI", original_uri(r));
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
add_header(t, "REMOTE_ADDR", r->useragent_ip);
|
||||
#else
|
||||
add_header(t, "REMOTE_ADDR", r->connection->remote_ip);
|
||||
#endif
|
||||
add_header(t, "REMOTE_PORT", apr_psprintf(r->pool, "%d", port));
|
||||
add_header(t, "REMOTE_USER", r->user);
|
||||
add_header(t, "DOCUMENT_ROOT", (char *) ap_document_root(r));
|
||||
|
||||
+61
-26
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI/mod_uwsgi ***
|
||||
|
||||
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
|
||||
Copyright 2009-2012 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
|
||||
@@ -37,11 +37,18 @@ LoadModule uwsgi_module <path_of_apache_modules>/mod_uwsgi.so
|
||||
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include "apr_strings.h"
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "httpd.h"
|
||||
#include "http_core.h"
|
||||
#include "http_protocol.h"
|
||||
#include "http_config.h"
|
||||
#include "http_log.h"
|
||||
#include "util_script.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
@@ -73,6 +80,7 @@ typedef struct {
|
||||
char scheme[9];
|
||||
int cgi_mode ;
|
||||
int max_vars;
|
||||
int empty_remote_user;
|
||||
} uwsgi_cfg;
|
||||
|
||||
module AP_MODULE_DECLARE_DATA uwsgi_module;
|
||||
@@ -161,6 +169,8 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
|
||||
c->modifier2 = 0 ;
|
||||
c->cgi_mode = 0 ;
|
||||
c->max_vars = 128;
|
||||
c->script_name[0] = 0;
|
||||
c->empty_remote_user = 1;
|
||||
|
||||
return c;
|
||||
}
|
||||
@@ -176,6 +186,13 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
|
||||
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;
|
||||
}
|
||||
@@ -336,8 +353,20 @@ static int uwsgi_handler(request_rec *r) {
|
||||
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) ;
|
||||
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->useragent_ip, &pkt_size) ;
|
||||
#else
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
|
||||
#endif
|
||||
|
||||
//
|
||||
if (r->user) {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user, &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) ;
|
||||
}
|
||||
@@ -347,31 +376,14 @@ static int uwsgi_handler(request_rec *r) {
|
||||
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, r, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
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) ;
|
||||
}
|
||||
// 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, r, "SCRIPT_NAME", "", &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri, &pkt_size) ;
|
||||
}
|
||||
else {
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", apr_pstrndup(r->pool, r->uri, (strlen(r->uri) - strlen(r->path_info) )) , &pkt_size) ;
|
||||
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->path_info, &pkt_size) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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) ;
|
||||
}
|
||||
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) ;
|
||||
}
|
||||
|
||||
|
||||
@@ -632,7 +644,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 ;
|
||||
}
|
||||
|
||||
@@ -733,6 +745,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"),
|
||||
@@ -741,6 +775,7 @@ 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}
|
||||
};
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import sys
|
||||
import uwsgi
|
||||
|
||||
print("i am the bootstrap for uwsgi.SymbolsImporter")
|
||||
sys.meta_path.insert(0, uwsgi.SymbolsImporter())
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import uwsgi
|
||||
|
||||
print uwsgi.extract("data://0")
|
||||
@@ -1,5 +1,5 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
xml = auto
|
||||
ini = true
|
||||
yaml = true
|
||||
json = auto
|
||||
@@ -15,19 +15,20 @@ 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, cache, 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
|
||||
@@ -35,6 +36,9 @@ event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, gevent
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = default
|
||||
bin_name = libuwsgi.so
|
||||
embedded_plugins = symcall
|
||||
embedded_plugins = null
|
||||
as_shared_library = 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
|
||||
+5
-5
@@ -2,8 +2,8 @@
|
||||
xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = true
|
||||
sqlite3 = true
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = false
|
||||
sctp = false
|
||||
@@ -15,12 +15,12 @@ threading = true
|
||||
sendfile = true
|
||||
minterpreters = true
|
||||
async = true
|
||||
evdis = false
|
||||
ldap = true
|
||||
pcre = false
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = libxml2
|
||||
xml_implementation = expat
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
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
|
||||
@@ -6,12 +6,7 @@ void uwsgi_init_cache() {
|
||||
int i;
|
||||
|
||||
if (!uwsgi.cache_blocksize)
|
||||
uwsgi.cache_blocksize = UMAX16;
|
||||
|
||||
if (uwsgi.cache_blocksize % uwsgi.page_size != 0) {
|
||||
uwsgi_log("invalid cache blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.cache_blocksize, uwsgi.page_size);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.cache_blocksize = UMAX16;
|
||||
|
||||
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) {
|
||||
@@ -88,155 +83,10 @@ void uwsgi_init_cache() {
|
||||
|
||||
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
|
||||
|
||||
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
|
||||
uwsgi_rwlock_init(uwsgi.cache_lock);
|
||||
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
|
||||
|
||||
uwsgi_log("*** Cache subsystem initialized: %dMB preallocated ***\n", ((sizeof(uint64_t) * UMAX16) + (sizeof(uint64_t) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024));
|
||||
}
|
||||
|
||||
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, struct uwsgi_subscribe_req *usr) {
|
||||
|
||||
char *ptr;
|
||||
uint64_t vallen = 0;
|
||||
struct uwsgi_subscriber *usub, nusub;
|
||||
int found = 0;
|
||||
int i;
|
||||
|
||||
ptr = uwsgi_dict_get(udict, usr->key, usr->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, usr->address, usr->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 = usr->address_len;
|
||||
usub->names[found].modifier1 = usr->modifier1;
|
||||
usub->names[found].modifier2 = usr->modifier2;
|
||||
memcpy(usub->names[found].name, usr->address, usr->address_len);
|
||||
if (found == (int) usub->nodes) {
|
||||
usub->nodes++;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
nusub.nodes = 1;
|
||||
nusub.current = 0;
|
||||
memcpy(nusub.names[0].name, usr->address, usr->address_len);
|
||||
nusub.names[0].modifier1 = usr->modifier1;
|
||||
nusub.names[0].modifier2 = usr->modifier2;
|
||||
uwsgi_dict_set(udict, usr->key, usr->keylen, (char *) &nusub, sizeof(struct uwsgi_subscriber));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_dict *uwsgi_dict_create(uint64_t items, uint64_t blocksize) {
|
||||
|
||||
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 (!blocksize) blocksize = 4096;
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
udict->blocksize = blocksize;
|
||||
udict->max_items = items;
|
||||
|
||||
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(udict->hashtable, 0, sizeof(uint64_t) * UMAX16);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
memset(udict->unused_stack, 0, sizeof(uint64_t) * udict->max_items);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
for(i=0;i< (int) udict->max_items;i++) {
|
||||
memset(&udict->items[i], 0, sizeof(struct uwsgi_dict_item));
|
||||
}
|
||||
|
||||
udict->first_available_item = 1;
|
||||
udict->unused_stack_ptr = 0;
|
||||
|
||||
udict->lock = uwsgi_mmap_shared_lock();
|
||||
uwsgi_lock_init(udict->lock);
|
||||
|
||||
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) {
|
||||
@@ -252,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);
|
||||
@@ -344,13 +111,14 @@ inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
|
||||
uint64_t slot = uwsgi.cache_hashtable[hash_key];
|
||||
|
||||
struct uwsgi_cache_item *uci;
|
||||
uint64_t rounds = 0;
|
||||
|
||||
//uwsgi_log("found slot %d for key %d\n", slot, hash_key);
|
||||
|
||||
uci = &uwsgi.cache_items[slot];
|
||||
|
||||
// first round
|
||||
if (uci->djbhash != hash) goto cycle;
|
||||
if (uci->djbhash != hash) return 0;
|
||||
if (uci->keysize != keylen) goto cycle;
|
||||
if (memcmp(uci->key, key, keylen)) goto cycle;
|
||||
|
||||
@@ -360,7 +128,20 @@ cycle:
|
||||
while(uci->next) {
|
||||
slot = uci->next;
|
||||
uci = &uwsgi.cache_items[slot];
|
||||
if (uci->djbhash != hash) continue;
|
||||
rounds++;
|
||||
if (rounds > uwsgi.cache_max_items) {
|
||||
uwsgi_log("ALARM !!! cache-loop (and potential deadlock) detected slot = %llu prev = %llu next = %llu\n", uci->next, slot, uci->prev, uci->next);
|
||||
// terrible case: the whole uWSGI stack can deadlock, leaving only the master alive
|
||||
// if the master is avalable, trigger a brutal reload
|
||||
if (uwsgi.master_process) {
|
||||
kill(uwsgi.workers[0].pid, SIGTERM);
|
||||
}
|
||||
// otherwise kill the current worker (could be pretty useless...)
|
||||
else {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if (uci->djbhash != hash) return 0;
|
||||
if (uci->keysize != keylen) continue;
|
||||
if (!memcmp(uci->key, key, keylen)) return slot;
|
||||
}
|
||||
@@ -387,13 +168,14 @@ char *uwsgi_cache_get(char *key, uint16_t keylen, uint64_t *valsize) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_cache_del(char *key, uint16_t keylen) {
|
||||
int uwsgi_cache_del(char *key, uint16_t keylen, uint64_t index) {
|
||||
|
||||
uint64_t index = 0;
|
||||
struct uwsgi_cache_item *uci;
|
||||
int ret = -1;
|
||||
|
||||
index = uwsgi_cache_get_index(key, keylen);
|
||||
if (!index)
|
||||
index = uwsgi_cache_get_index(key, keylen);
|
||||
|
||||
if (index) {
|
||||
uci = &uwsgi.cache_items[index] ;
|
||||
uci->keysize = 0;
|
||||
@@ -410,9 +192,15 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
|
||||
if (uci->prev) {
|
||||
uwsgi.cache_items[uci->prev].next = uci->next;
|
||||
}
|
||||
else {
|
||||
// set next as the new entry point (could be 0)
|
||||
uwsgi.cache_hashtable[uci->djbhash % 0xffff] = uci->next;
|
||||
}
|
||||
|
||||
if (uci->next) {
|
||||
uwsgi.cache_items[uci->next].prev = uci->prev;
|
||||
}
|
||||
|
||||
if (!uci->prev && !uci->next) {
|
||||
// reset hashtable entry
|
||||
//uwsgi_log("!!! resetted hashtable entry !!!\n");
|
||||
@@ -421,6 +209,7 @@ int uwsgi_cache_del(char *key, uint16_t keylen) {
|
||||
uci->djbhash = 0;
|
||||
uci->prev = 0;
|
||||
uci->next = 0;
|
||||
uci->expires = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -495,6 +284,9 @@ int uwsgi_cache_set(char *key, uint16_t keylen, char *val, uint64_t vallen, uint
|
||||
ret = 0;
|
||||
// now put the value in the 16bit hashtable
|
||||
slot = uci->djbhash % 0xffff;
|
||||
// reset values
|
||||
uci->prev = 0;
|
||||
uci->next = 0;
|
||||
|
||||
if (uwsgi.cache_hashtable[slot] == 0) {
|
||||
uwsgi.cache_hashtable[slot] = index;
|
||||
@@ -512,7 +304,7 @@ 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) {
|
||||
else if (flags & UWSGI_CACHE_FLAG_UPDATE) {
|
||||
uci = &uwsgi.cache_items[index] ;
|
||||
if (expires) {
|
||||
expires += time(NULL);
|
||||
@@ -528,71 +320,6 @@ end:
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_dict_set(struct uwsgi_dict *udict, char *key, uint16_t keylen, char *val, uint64_t vallen) {
|
||||
|
||||
uint64_t index = 0, last_index = 0 ;
|
||||
|
||||
struct uwsgi_dict_item *udi, *udii;
|
||||
|
||||
int ret = -1;
|
||||
int slot;
|
||||
|
||||
if (!keylen || !vallen) return -1;
|
||||
|
||||
if (keylen > UWSGI_CACHE_MAX_KEY_SIZE) return -1;
|
||||
|
||||
if (udict->first_available_item >= udict->max_items && !udict->unused_stack_ptr) {
|
||||
uwsgi_log("*** DANGER dictionary %p is FULL !!! ***\n", udict);
|
||||
goto end;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
/* THIS PART IS HEAVILY OPTIMIZED: PERFORMANCE NOT ELEGANCE !!! */
|
||||
|
||||
void *cache_thread_loop(void *fd_ptr) {
|
||||
|
||||
@@ -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();
|
||||
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
|
||||
|
||||
+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,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;
|
||||
}
|
||||
@@ -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)
|
||||
+21
-10
@@ -10,8 +10,8 @@ import time
|
||||
|
||||
# register rpc function helloworld
|
||||
@rpc("helloworld")
|
||||
def hello_world():
|
||||
return "Hello World"
|
||||
def hello2():
|
||||
return "[RPC] Hello World"
|
||||
|
||||
# register signal 1
|
||||
@signal(1)
|
||||
@@ -45,6 +45,7 @@ def tmpmodified(num):
|
||||
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
|
||||
@@ -52,10 +53,12 @@ def a_long_task(args):
|
||||
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 60 seconds
|
||||
# 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)))
|
||||
@@ -89,7 +92,10 @@ def a_running_thread_with_args(who):
|
||||
def a_post_fork_thread():
|
||||
while True:
|
||||
time.sleep(3)
|
||||
print("Hello from a thread in worker %d" % uwsgi.worker_id())
|
||||
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():
|
||||
@@ -97,24 +103,29 @@ def fork_happened():
|
||||
|
||||
@postfork
|
||||
def fork_happened2():
|
||||
print("waiting for a signal...")
|
||||
uwsgi.signal_wait()
|
||||
print("signal received: %d" % uwsgi.signal_received())
|
||||
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, 100):
|
||||
time.sleep(0.2)
|
||||
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)
|
||||
delayed_task.spool(foo2='bar2', at=time.time()+60)
|
||||
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')
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -8,6 +8,8 @@ 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;
|
||||
@@ -32,6 +34,9 @@ struct uwsgi_instance {
|
||||
int loyal;
|
||||
|
||||
int zerg;
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
};
|
||||
|
||||
|
||||
@@ -166,22 +171,29 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
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, char *config, uint32_t config_size) {
|
||||
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;
|
||||
char **vassal_argv;
|
||||
char *uef;
|
||||
char **uenvs;
|
||||
int counter;
|
||||
char *colon = NULL;
|
||||
int i;
|
||||
|
||||
sleep(1);
|
||||
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;
|
||||
@@ -209,6 +221,8 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
|
||||
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;
|
||||
@@ -253,6 +267,24 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
}
|
||||
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");
|
||||
|
||||
@@ -282,7 +314,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
break;
|
||||
}
|
||||
free(oe);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("putenv %s\n", ne);
|
||||
#endif
|
||||
|
||||
if (putenv(ne)) {
|
||||
uwsgi_error("putenv()");
|
||||
@@ -302,15 +336,15 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
}
|
||||
|
||||
counter = 4;
|
||||
struct uwsgi_config_template *uct = uwsgi.vassals_templates;
|
||||
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
|
||||
while(uct) {
|
||||
counter+=2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
argv[0] = uwsgi.binary_path;
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(name, ':');
|
||||
@@ -318,33 +352,65 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
}
|
||||
// initialize to a default value
|
||||
vassal_argv[1] = "--inherit";
|
||||
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
argv[1] = "--xml";
|
||||
vassal_argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
argv[1] = "--ini";
|
||||
vassal_argv[1] = "--ini";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".yml"))
|
||||
argv[1] = "--yaml";
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
|
||||
argv[1] = "--yaml";
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 3), ".js"))
|
||||
argv[1] = "--json";
|
||||
vassal_argv[1] = "--json";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
argv[2] = name;
|
||||
|
||||
|
||||
vassal_argv[2] = name;
|
||||
if (uwsgi.emperor_magic_exec) {
|
||||
if (!access(name, R_OK|X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
counter = 3;
|
||||
uct = uwsgi.vassals_templates;
|
||||
while(uct) {
|
||||
argv[counter] = "--inherit";
|
||||
argv[counter+1] = uct->filename;
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter+1] = uct->value;
|
||||
counter+=2;
|
||||
uct = uct->next;
|
||||
}
|
||||
argv[counter] = NULL;
|
||||
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<sysconf(_SC_OPEN_MAX);i++) {
|
||||
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);
|
||||
}
|
||||
@@ -360,7 +426,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
|
||||
}
|
||||
|
||||
// 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");
|
||||
@@ -399,6 +465,9 @@ void emperor_loop() {
|
||||
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);
|
||||
@@ -408,6 +477,13 @@ void emperor_loop() {
|
||||
|
||||
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
|
||||
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl)) {
|
||||
uwsgi_error("getrlimit()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi.max_fd = rl.rlim_cur;
|
||||
|
||||
|
||||
emperor_queue = event_queue_init();
|
||||
|
||||
@@ -420,6 +496,23 @@ void emperor_loop() {
|
||||
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) {
|
||||
@@ -459,7 +552,12 @@ reconnect:
|
||||
uwsgi_error("glob()");
|
||||
exit(1);
|
||||
}
|
||||
emperor_absolute_dir = realpath(".", NULL);
|
||||
globfree(&g);
|
||||
emperor_absolute_dir = uwsgi_malloc(PATH_MAX+1);
|
||||
if (realpath(".", emperor_absolute_dir) == NULL) {
|
||||
uwsgi_error("realpath()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ui = &ui_base;
|
||||
@@ -517,7 +615,7 @@ reconnect:
|
||||
}
|
||||
else {
|
||||
if (msgsize > 0) {
|
||||
emperor_add(config_file, time(NULL), config, msgsize);
|
||||
emperor_add(config_file, time(NULL), config, msgsize, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -554,13 +652,16 @@ reconnect:
|
||||
emperor_respawn(ui_current, time(NULL));
|
||||
}
|
||||
else {
|
||||
emperor_add(config_file, time(NULL), NULL, 0);
|
||||
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) {
|
||||
@@ -568,7 +669,9 @@ reconnect:
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
if (!ui_current->config_len) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (byte == 17) {
|
||||
@@ -583,13 +686,13 @@ reconnect:
|
||||
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);
|
||||
emperor_add(zerg_name, time(NULL), NULL, 0, ui_current->uid, ui_current->gid);
|
||||
free(zerg_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unrecognized event on fd %d\n", interesting_fd);
|
||||
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);
|
||||
}
|
||||
@@ -604,7 +707,8 @@ reconnect:
|
||||
!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) - 3), ".js") ||
|
||||
!strcmp(de->d_name + (strlen(de->d_name) - 5), ".json")
|
||||
) {
|
||||
|
||||
|
||||
@@ -620,13 +724,21 @@ reconnect:
|
||||
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, NULL, 0);
|
||||
emperor_add(de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -643,6 +755,7 @@ reconnect:
|
||||
!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")
|
||||
) {
|
||||
|
||||
@@ -659,17 +772,26 @@ reconnect:
|
||||
ui_current = emperor_get(g.gl_pathv[i]);
|
||||
|
||||
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(g.gl_pathv[i], st.st_mtime, NULL, 0);
|
||||
emperor_add(g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
globfree(&g);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -729,7 +851,7 @@ reconnect:
|
||||
}
|
||||
else {
|
||||
// UNSAFE
|
||||
emperor_add(ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len);
|
||||
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;
|
||||
@@ -748,3 +870,73 @@ reconnect:
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#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;
|
||||
@@ -417,7 +421,8 @@ int event_queue_interesting_fd(void *events, int id) {
|
||||
int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
struct kevent *ev = (struct kevent *) events;
|
||||
|
||||
if ( ( (ev[id].flags == EV_ERROR) || (ev[id].flags == EV_EOF) || (ev[id].flags == (EV_EOF|EV_ERROR))) ) {
|
||||
// DO NOT CHECK FOR EOF !!!
|
||||
if ( ev[id].flags & EV_ERROR ) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
@@ -441,7 +446,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 +482,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 +512,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 +571,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) {
|
||||
@@ -657,6 +673,8 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
|
||||
@@ -687,13 +705,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
|
||||
|
||||
@@ -765,7 +793,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;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
use POSIX;
|
||||
|
||||
open CONFIG,'welcome.ini';
|
||||
|
||||
dup2(fileno(CONFIG), 17);
|
||||
|
||||
exec './uwsgi','--ini','fd://17';
|
||||
@@ -2,121 +2,76 @@
|
||||
|
||||
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
|
||||
|
||||
if (!uwsgi.sockets) {
|
||||
// wait for child end
|
||||
//waitpid(-1, &i, 0);
|
||||
}
|
||||
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);
|
||||
}
|
||||
@@ -124,10 +79,78 @@ void gateway_respawn(int id) {
|
||||
ug->pid = gw_pid;
|
||||
ug->respawns++;
|
||||
if (ug->respawns == 1) {
|
||||
uwsgi_log( "spawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "respawned uWSGI %s %d (pid: %d)\n", ug->name, ug->num, (int) gw_pid);
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
+18
-1
@@ -1,6 +1,23 @@
|
||||
import uwsgi
|
||||
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
|
||||
if uwsgi.loop == 'gevent':
|
||||
import gevent
|
||||
|
||||
print uwsgi.version
|
||||
print uwsgi.workers()
|
||||
try:
|
||||
uwsgi.cache_set('foo', "Hello World from cache")
|
||||
except:
|
||||
pass
|
||||
def application(env, start_response):
|
||||
if uwsgi.loop == 'gevent':
|
||||
gevent.sleep()
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
yield "foobar<br/>"
|
||||
if uwsgi.loop == 'gevent':
|
||||
gevent.sleep(3)
|
||||
yield str(env['wsgi.input'].fileno())
|
||||
yield "<h1>Hello World</h1>"
|
||||
try:
|
||||
yield uwsgi.cache_get('foo')
|
||||
except:
|
||||
pass
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
char *section_asked = "uwsgi";
|
||||
char *colon;
|
||||
|
||||
if (!uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6) ) {
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
colon = uwsgi_get_last_char(file, '/');
|
||||
colon = uwsgi_get_last_char(colon, ':');
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
char *colon;
|
||||
int i;
|
||||
|
||||
if (!uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6)) {
|
||||
if (uwsgi_check_scheme(file)) {
|
||||
colon = uwsgi_get_last_char(file, '/');
|
||||
colon = uwsgi_get_last_char(colon, ':');
|
||||
}
|
||||
@@ -77,10 +77,10 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
add_exported_option((char *)key, (char *) json_string_value(config_value), 0);
|
||||
}
|
||||
else if (json_is_true(config_value)) {
|
||||
add_exported_option((char *)key, (char *) "1", 0);
|
||||
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, (char *) "0", 0);
|
||||
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);
|
||||
@@ -92,10 +92,10 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
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, (char *) "1", 0);
|
||||
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, (char *) "0", 0);
|
||||
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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
+3
-34
@@ -27,22 +27,6 @@ struct amqp_frame_method {
|
||||
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_longstr(char *ptr, char *watermark) {
|
||||
|
||||
uint32_t longstr_size;
|
||||
|
||||
if (ptr+4 > watermark) return NULL;
|
||||
|
||||
memcpy(&longstr_size, ptr, 4);
|
||||
longstr_size = ntohl(longstr_size);
|
||||
|
||||
if (ptr+4+longstr_size > watermark) return NULL;
|
||||
|
||||
return ptr+4+longstr_size;
|
||||
}
|
||||
*/
|
||||
|
||||
static char *amqp_get_str(char *ptr, char *watermark) {
|
||||
|
||||
uint8_t str_size;
|
||||
@@ -58,23 +42,6 @@ static char *amqp_get_str(char *ptr, char *watermark) {
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
static char *amqp_get_table(char *ptr, char *watermark) {
|
||||
|
||||
uint32_t table_size;
|
||||
|
||||
if (ptr+4 > watermark) return NULL;
|
||||
|
||||
memcpy(&table_size, ptr, 4);
|
||||
|
||||
table_size = ntohl(table_size);
|
||||
|
||||
if (ptr+4+table_size > watermark) return NULL;
|
||||
|
||||
return ptr+4+table_size;
|
||||
}
|
||||
*/
|
||||
|
||||
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
|
||||
|
||||
uint16_t tmp_short;
|
||||
@@ -197,7 +164,9 @@ char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
|
||||
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;
|
||||
@@ -501,7 +470,7 @@ static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
|
||||
|
||||
len = 0;
|
||||
|
||||
char *frame = malloc(fh->size+1);
|
||||
char *frame = uwsgi_malloc(fh->size+1);
|
||||
ptr = frame;
|
||||
|
||||
while(len < fh->size+1) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -33,6 +33,22 @@ void linux_namespace_start(void *argv) {
|
||||
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) {
|
||||
|
||||
@@ -1,5 +1,20 @@
|
||||
#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>
|
||||
|
||||
+1
-1
@@ -19,7 +19,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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,195 +1,549 @@
|
||||
#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)
|
||||
#ifdef EOWNERDEAD
|
||||
#define UWSGI_LOCK_ENGINE_NAME "pthread robust mutexes"
|
||||
#else
|
||||
#define UWSGI_LOCK_ENGINE_NAME "pthread mutexes"
|
||||
#endif
|
||||
|
||||
#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)) {
|
||||
#ifdef EOWNERDEAD
|
||||
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP)) {
|
||||
uwsgi_log("unable to make the mutex 'robust'\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
|
||||
uwsgi_log("unable to initialize mutex\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_mutexattr_destroy(&attr);
|
||||
|
||||
#ifndef EOWNERDEAD
|
||||
uli->can_deadlock = 1;
|
||||
#endif
|
||||
|
||||
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_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
|
||||
#ifdef EOWNERDEAD
|
||||
if (pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr) == EOWNERDEAD) {
|
||||
uwsgi_log("[deadlock-detector] a process holding a robust mutex died. recovering...\n");
|
||||
pthread_mutex_consistent_np((pthread_mutex_t *) uli->lock_ptr);
|
||||
}
|
||||
#else
|
||||
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
|
||||
#endif
|
||||
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));
|
||||
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(void *lock) {
|
||||
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
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(void *lock) {
|
||||
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
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(void *lock) {
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
|
||||
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
|
||||
}
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
return uwsgi_lock_fast_init(id);
|
||||
#else
|
||||
|
||||
void uwsgi_unlock(void *lock) {
|
||||
pthread_rwlockattr_t attr;
|
||||
|
||||
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
|
||||
}
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
|
||||
|
||||
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); }
|
||||
|
||||
#elif defined(UWSGI_LOCK_USE_POSIX_SEM)
|
||||
|
||||
#define UWSGI_LOCK_SIZE sizeof(sem_t)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(sem_t)
|
||||
#define UWSGI_LOCK_ENGINE_NAME "POSIX semaphores"
|
||||
|
||||
#include <semaphore.h>
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
sem_init((sem_t*) uli->lock_ptr, 1, 1);
|
||||
uli->can_deadlock = 1;
|
||||
return uli;
|
||||
}
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) { return uwsgi_lock_fast_init(id) ;}
|
||||
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
sem_wait((sem_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
sem_post((sem_t*) uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (sem_trywait((sem_t *) uli->lock_ptr) == 0) {
|
||||
sem_post((sem_t*) uli->lock_ptr);
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(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);}
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(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);
|
||||
|
||||
void uwsgi_lock_init(void *lock) {
|
||||
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);
|
||||
}
|
||||
|
||||
FILE *tf = tmpfile();
|
||||
int fd;
|
||||
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));
|
||||
|
||||
if (!tf) {
|
||||
uwsgi_error_open("temp lock file");
|
||||
semu.val = 1;
|
||||
if (semctl(semid, 0, SETVAL, semu)) {
|
||||
uwsgi_error("semctl()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fd = fileno(tf);
|
||||
|
||||
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_initial("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_initial("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_SET;
|
||||
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_SET;
|
||||
fl.l_start = 0;
|
||||
fl.l_len = 0;
|
||||
fl.l_pid = 0;
|
||||
|
||||
if (fcntl(fd, F_SETLK, &fl)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
@@ -19,10 +19,101 @@
|
||||
|
||||
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)
|
||||
char *time_request;
|
||||
char time_request[26];
|
||||
time_t microseconds, microseconds2;
|
||||
int rlen;
|
||||
int app_req = -1;
|
||||
@@ -44,10 +135,13 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
#ifdef UWSGI_SENDFILE
|
||||
char *msg1 = " via sendfile() ";
|
||||
#endif
|
||||
char *msg3 = " via route() ";
|
||||
char *msg4 = " via offload() ";
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
if (wsgi_req->do_not_log) return ;
|
||||
if (wsgi_req->do_not_log)
|
||||
return;
|
||||
|
||||
if (wsgi_req->app_id >= 0) {
|
||||
wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
@@ -57,12 +151,24 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
|
||||
// mark route() requests
|
||||
if (wsgi_req->status == -17) {
|
||||
via = msg3;
|
||||
}
|
||||
else if (wsgi_req->status == -30) {
|
||||
via = msg4;
|
||||
}
|
||||
|
||||
#ifdef __sun__
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, time_request, 26);
|
||||
#else
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, time_request);
|
||||
#endif
|
||||
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;
|
||||
|
||||
@@ -87,12 +193,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;
|
||||
@@ -101,59 +204,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);
|
||||
}
|
||||
@@ -164,8 +248,8 @@ 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;
|
||||
@@ -184,8 +268,15 @@ void get_memusage() {
|
||||
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(UWSGI_NEW_OPENBSD)
|
||||
struct kinfo_proc *kproc;
|
||||
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, sizeof(struct kinfo_proc), &cnt);
|
||||
if (kproc && cnt > 0) {
|
||||
*vsz = (kproc->p_vm_dsize + kproc->p_vm_ssize + kproc->p_vm_tsize) * uwsgi.page_size;
|
||||
*rss = kproc->p_vm_rssize * uwsgi.page_size;
|
||||
}
|
||||
#elif defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
struct kinfo_proc2 *kproc2;
|
||||
@@ -193,11 +284,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
|
||||
|
||||
@@ -207,13 +298,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=
|
||||
@@ -40,9 +40,9 @@ 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;
|
||||
|
||||
@@ -55,8 +55,11 @@ void *simple_loop(void *arg1) {
|
||||
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);
|
||||
}
|
||||
@@ -117,7 +120,6 @@ void *zeromq_loop(void *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) {
|
||||
|
||||
@@ -128,8 +130,11 @@ void *zeromq_loop(void *arg1) {
|
||||
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);
|
||||
}
|
||||
@@ -182,38 +187,12 @@ void *zeromq_loop(void *arg1) {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(uwsgi.signal_socket, "worker", 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);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(uwsgi.my_signal_socket, "worker", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
+708
-90
@@ -2,6 +2,333 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void worker_wakeup() {
|
||||
}
|
||||
|
||||
int uwsgi_calc_cheaper(void) {
|
||||
|
||||
int i;
|
||||
static time_t last_check = 0;
|
||||
int check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
|
||||
if (!last_check) last_check = time(NULL);
|
||||
|
||||
time_t now = time(NULL);
|
||||
if (!check_interval)
|
||||
check_interval = 1;
|
||||
|
||||
if ( (now - last_check) < check_interval) return 1;
|
||||
|
||||
last_check = now;
|
||||
|
||||
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->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
#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;
|
||||
@@ -31,71 +358,152 @@ void master_check_cluster_nodes() {
|
||||
}
|
||||
}
|
||||
|
||||
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.master_process) {
|
||||
if (uwsgi.signal_pipe[wid][0] != -1) close(uwsgi.signal_pipe[wid][0]);
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, uwsgi.signal_pipe[wid])) {
|
||||
uwsgi_error("socketpair()\n");
|
||||
}
|
||||
if (uwsgi.threaded_logger) {
|
||||
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
|
||||
|
||||
pid_t pid = fork();
|
||||
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].requests = 0;
|
||||
uwsgi.workers[uwsgi.mywid].failed_requests = 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;
|
||||
|
||||
// close the cache server
|
||||
if (uwsgi.cache_server_fd != -1) {
|
||||
close(uwsgi.cache_server_fd);
|
||||
}
|
||||
// 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) {
|
||||
// fix the communication pipe
|
||||
close(uwsgi.shared->worker_signal_pipe[0]);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (uwsgi.signal_pipe[i][0] != -1) {
|
||||
close(uwsgi.signal_pipe[i][0]);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi.my_signal_socket = uwsgi.signal_pipe[wid][1];
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
|
||||
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
|
||||
}
|
||||
#endif
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
else if (pid < 1) {
|
||||
uwsgi_error("fork()");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.master_process) {
|
||||
close(uwsgi.signal_pipe[wid][1]);
|
||||
}
|
||||
if (respawns > 0) {
|
||||
uwsgi_log("Respawned uWSGI worker %d (new pid: %d)\n", wid, (int) pid);
|
||||
}
|
||||
@@ -104,6 +512,11 @@ int uwsgi_respawn_worker(int wid) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.threaded_logger) {
|
||||
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -113,8 +526,7 @@ void uwsgi_manage_signal_cron(time_t now) {
|
||||
struct tm *uwsgi_cron_delta;
|
||||
int i;
|
||||
|
||||
uwsgi.current_time = now;
|
||||
uwsgi_cron_delta = localtime(&uwsgi.current_time);
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
if (uwsgi_cron_delta) {
|
||||
|
||||
@@ -133,42 +545,52 @@ void uwsgi_manage_signal_cron(time_t now) {
|
||||
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;
|
||||
|
||||
// mday and wday are ORed
|
||||
if (ucron->day == -1 && ucron->week == -1) {
|
||||
if (ucron->day == -1)
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (ucron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (ucron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (ucron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (ucron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (ucron->week == -1)
|
||||
}
|
||||
}
|
||||
if (ucron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
else if (ucron->day == -1) {
|
||||
ucron->day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
else if (ucron->week == -1) {
|
||||
ucron->week = uwsgi_cron_delta->tm_wday;
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (ucron->day >= 0 && ucron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (ucron->day == uwsgi_cron_delta->tm_mday) {
|
||||
ucron->week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
else if (ucron->week == uwsgi_cron_delta->tm_wday) {
|
||||
ucron->day = uwsgi_cron_delta->tm_mday;
|
||||
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 (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) {
|
||||
|
||||
|
||||
if (run_task == 1) {
|
||||
// date match, signal it ?
|
||||
if (uwsgi.current_time - ucron->last_job > 60) {
|
||||
if (now - ucron->last_job > 60) {
|
||||
uwsgi_route_signal(ucron->sig);
|
||||
ucron->last_job = uwsgi.current_time;
|
||||
ucron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,8 +610,7 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
struct uwsgi_cron *current_cron = uwsgi.crons;
|
||||
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
|
||||
|
||||
uwsgi.current_time = now;
|
||||
uwsgi_cron_delta = localtime(&uwsgi.current_time);
|
||||
uwsgi_cron_delta = localtime(&now);
|
||||
|
||||
|
||||
if (!uwsgi_cron_delta) {
|
||||
@@ -197,8 +618,10 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
return;
|
||||
}
|
||||
|
||||
while (current_cron) {
|
||||
// fix month
|
||||
uwsgi_cron_delta->tm_mon++;
|
||||
|
||||
while (current_cron) {
|
||||
|
||||
uc_minute = current_cron->minute;
|
||||
uc_hour = current_cron->hour;
|
||||
@@ -206,47 +629,58 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
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;
|
||||
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day == -1 && current_cron->week == -1) {
|
||||
if (current_cron->day == -1)
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (current_cron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (current_cron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (current_cron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (current_cron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (current_cron->week == -1)
|
||||
}
|
||||
}
|
||||
if (current_cron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
else if (current_cron->day == -1) {
|
||||
current_cron->day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
else if (current_cron->week == -1) {
|
||||
current_cron->week = uwsgi_cron_delta->tm_wday;
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day >= 0 && current_cron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (current_cron->day == uwsgi_cron_delta->tm_mday) {
|
||||
current_cron->week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
else if (current_cron->week == uwsgi_cron_delta->tm_wday) {
|
||||
current_cron->day = uwsgi_cron_delta->tm_mday;
|
||||
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 (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) {
|
||||
|
||||
if (run_task == 1) {
|
||||
|
||||
// date match, run command ?
|
||||
if (uwsgi.current_time - current_cron->last_job > 60) {
|
||||
if (now - current_cron->last_job > 60) {
|
||||
//call command
|
||||
if (current_cron->command) {
|
||||
if (uwsgi_run_command(current_cron->command) >=0) {
|
||||
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 = uwsgi.current_time;
|
||||
current_cron->last_job = now;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -257,3 +691,187 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
#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", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]);
|
||||
stats_send_llu("\"listen_queue_errors\": %llu,\n", (unsigned long long) uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]);
|
||||
#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);
|
||||
stats_send_llu("\"static_offload_threads\": %llu, ", uwsgi.workers[i + 1].static_offload_threads);
|
||||
|
||||
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,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>
|
||||
|
||||
@@ -2,30 +2,16 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option, int absolute) {
|
||||
|
||||
void *plugin_handle;
|
||||
|
||||
char *plugin_name;
|
||||
char *plugin_entry_symbol;
|
||||
struct uwsgi_plugin *up;
|
||||
char linkpath_buf[1024], linkpath[1024];
|
||||
int linkpath_size;
|
||||
static int plugin_already_loaded(const char *plugin) {
|
||||
int i;
|
||||
|
||||
char *colon = strchr(plugin, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
|
||||
check:
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
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
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (uwsgi.p[i]->alias) {
|
||||
@@ -33,7 +19,7 @@ check:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +31,7 @@ check:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
if (uwsgi.gp[i]->alias) {
|
||||
@@ -53,48 +39,101 @@ check:
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%s plugin already available\n", plugin);
|
||||
#endif
|
||||
return NULL;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
|
||||
|
||||
void *plugin_handle = NULL;
|
||||
char *plugin_abs_path = NULL;
|
||||
char *plugin_filename = NULL;
|
||||
|
||||
int need_free = 0;
|
||||
char *plugin_name = plugin;
|
||||
char *plugin_symbol_name_start = plugin;
|
||||
|
||||
|
||||
struct uwsgi_plugin *up;
|
||||
char linkpath_buf[1024], linkpath[1024];
|
||||
int linkpath_size;
|
||||
|
||||
char *colon = strchr(plugin_name, ':');
|
||||
if (colon) {
|
||||
plugin = colon+1;
|
||||
colon[0] = 0;
|
||||
modifier = atoi(plugin_name);
|
||||
plugin_name = colon+1;
|
||||
colon[0] = ':';
|
||||
colon = NULL;
|
||||
goto check;
|
||||
}
|
||||
|
||||
if (absolute == 1) {
|
||||
plugin_name = uwsgi_concat2(plugin, "");
|
||||
// need to fix this... postpone until needed
|
||||
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
|
||||
}
|
||||
else if (absolute == 2) {
|
||||
plugin_name = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin);
|
||||
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
|
||||
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
|
||||
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
|
||||
need_free = 1;
|
||||
}
|
||||
else {
|
||||
plugin_name = uwsgi_concat4(UWSGI_PLUGIN_DIR, "/", plugin, "_plugin.so");
|
||||
plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin");
|
||||
}
|
||||
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
|
||||
|
||||
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) {
|
||||
if (!has_option)
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
goto end;
|
||||
}
|
||||
plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/');
|
||||
plugin_symbol_name_start++;
|
||||
plugin_abs_path = plugin_name;
|
||||
goto success;
|
||||
}
|
||||
|
||||
// step dir, check for user-supplied plugins directory
|
||||
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
|
||||
while(pdir) {
|
||||
plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
|
||||
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
|
||||
if (plugin_handle) {
|
||||
plugin_abs_path = plugin_filename;
|
||||
//free(plugin_filename);
|
||||
goto success;
|
||||
}
|
||||
free(plugin_filename);
|
||||
plugin_filename = NULL;
|
||||
pdir = pdir->next;
|
||||
}
|
||||
|
||||
// last step: search in compile-time plugin_dir
|
||||
if (!plugin_handle) {
|
||||
plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
|
||||
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
|
||||
plugin_abs_path = plugin_filename;
|
||||
//free(plugin_filename);
|
||||
}
|
||||
|
||||
success:
|
||||
if (!plugin_handle) {
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
if (!has_option)
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
else {
|
||||
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) {
|
||||
if ((linkpath_size = readlink(plugin_abs_path, linkpath_buf, 1023)) > 0) {
|
||||
do {
|
||||
linkpath_buf[linkpath_size] = '\0';
|
||||
strcpy(linkpath, linkpath_buf);
|
||||
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, '/');
|
||||
@@ -109,23 +148,47 @@ check:
|
||||
}
|
||||
}
|
||||
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);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
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);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
if (has_option) {
|
||||
struct option *lopt = up->options, *aopt;
|
||||
struct uwsgi_option *op = up->options;
|
||||
int found = 0;
|
||||
while ((aopt = lopt)) {
|
||||
if (!aopt->name)
|
||||
break;
|
||||
if (!strcmp(has_option, aopt->name)) {
|
||||
while (op && op->name) {
|
||||
if (!strcmp(has_option, op->name)) {
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
lopt++;
|
||||
op++;
|
||||
}
|
||||
if (!found) {
|
||||
if (dlclose(plugin_handle)) {
|
||||
uwsgi_error("dlclose()");
|
||||
}
|
||||
free(plugin_name);
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
free(plugin_entry_symbol);
|
||||
return NULL;
|
||||
}
|
||||
@@ -137,14 +200,77 @@ check:
|
||||
else {
|
||||
fill_plugin_table(up->modifier1, up);
|
||||
}
|
||||
free(plugin_name);
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
free(plugin_entry_symbol);
|
||||
|
||||
if (up->on_load)
|
||||
up->on_load();
|
||||
return plugin_handle;
|
||||
}
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
if (!has_option)
|
||||
uwsgi_log( "%s\n", dlerror());
|
||||
}
|
||||
|
||||
free(plugin_name);
|
||||
end:
|
||||
if (need_free)
|
||||
free(plugin_name);
|
||||
if (plugin_filename)
|
||||
free(plugin_filename);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_try_autoload(char *option) {
|
||||
DIR *d;
|
||||
struct dirent *dp;
|
||||
// step dir, check for user-supplied plugins directory
|
||||
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
|
||||
while(pdir) {
|
||||
d = opendir(pdir->value);
|
||||
if (d) {
|
||||
while ((dp = readdir(d)) != NULL) {
|
||||
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
|
||||
char *filename = uwsgi_concat3(pdir->value, "/", dp->d_name);
|
||||
if (uwsgi_load_plugin(-1, filename, option)) {
|
||||
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
|
||||
free(filename);
|
||||
closedir(d);
|
||||
// add new options
|
||||
build_options();
|
||||
return 1;
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
}
|
||||
closedir(d);
|
||||
}
|
||||
pdir = pdir->next;
|
||||
}
|
||||
|
||||
// last step: search in compile-time plugin_dir
|
||||
d = opendir(UWSGI_PLUGIN_DIR);
|
||||
if (!d) return 0;
|
||||
|
||||
while((dp = readdir(d)) != NULL) {
|
||||
if (uwsgi_endswith(dp->d_name, "_plugin.so")) {
|
||||
char *filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", dp->d_name);
|
||||
if (uwsgi_load_plugin(-1, filename, option)) {
|
||||
uwsgi_log("option \"%s\" found in plugin %s\n", option, filename);
|
||||
free(filename);
|
||||
closedir(d);
|
||||
// add new options
|
||||
build_options();
|
||||
return 1;
|
||||
}
|
||||
free(filename);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(d);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
Vendored
+4
-3
@@ -34,6 +34,7 @@ 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) {
|
||||
@@ -52,9 +53,9 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
// set
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
argc = 3;
|
||||
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
|
||||
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, argvs, &argc)) {
|
||||
if (argc > 1) {
|
||||
uwsgi_cache_set(argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), 0, 0);
|
||||
uwsgi_cache_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -62,7 +63,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
|
||||
case 2:
|
||||
// del
|
||||
if (wsgi_req->uh.pktsize > 0) {
|
||||
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize);
|
||||
uwsgi_cache_del(wsgi_req->buffer, wsgi_req->uh.pktsize, 0);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_carbon {
|
||||
struct uwsgi_string_list *servers;
|
||||
int freq;
|
||||
int timeout;
|
||||
char *id;
|
||||
int no_workers;
|
||||
} 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},
|
||||
{"carbon-no-workers", no_argument, 0, "disable generation of single worker metrics", uwsgi_opt_true, &u_carbon.no_workers, 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;}
|
||||
|
||||
if (u_carbon.no_workers) goto gmetrics;
|
||||
|
||||
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;}
|
||||
}
|
||||
|
||||
gmetrics:
|
||||
|
||||
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']
|
||||
+889
-45
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,70 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
/*
|
||||
|
||||
This plugins is meant as an example for custom implementations.
|
||||
|
||||
-- Copy of 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.
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int cheaper_backlog2_algo(void) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
int backlog = uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS];
|
||||
#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) {
|
||||
// count active workers
|
||||
int active_workers = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
active_workers++;
|
||||
}
|
||||
}
|
||||
|
||||
// cheap a worker if too much are running
|
||||
if (active_workers > uwsgi.cheaper_count) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// registration hook
|
||||
void uwsgi_cheaper_register_backlog2(void) {
|
||||
uwsgi_register_cheaper_algo("backlog2", cheaper_backlog2_algo);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin cheaper_backlog2_plugin = {
|
||||
|
||||
.name = "cheaper_backlog2",
|
||||
.on_load = uwsgi_cheaper_register_backlog2,
|
||||
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='cheaper_backlog2'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['cheaper_backlog2']
|
||||
@@ -40,7 +40,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
fc = new FakeClass();
|
||||
// get PATH_INFO
|
||||
fc->foobar = uwsgi_get_var(wsgi_req, (char *) "PATH_INFO", &fc->foobar_len);
|
||||
fc->foobar = uwsgi_get_var(wsgi_req, (char *) "PATH_INFO", 9, &fc->foobar_len);
|
||||
|
||||
if (fc->foobar) {
|
||||
// send output
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
int dummy_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin dummy_plugin = {
|
||||
.name = "dummy",
|
||||
.modifier1 = 0,
|
||||
.request = dummy_request,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='dummy'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['dummy']
|
||||
+35
-49
@@ -4,10 +4,10 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_erlang uerl;
|
||||
|
||||
struct option erlang_options[] = {
|
||||
{"erlang", required_argument, 0, LONG_ARGS_ERLANG},
|
||||
{"erlang-cookie", required_argument, 0, LONG_ARGS_ERLANG_COOKIE},
|
||||
{0, 0, 0, 0},
|
||||
struct uwsgi_option erlang_options[] = {
|
||||
{"erlang", required_argument, 0, "spawn an erlang c-node", uwsgi_opt_set_str, &uerl.name, UWSGI_OPT_MASTER},
|
||||
{"erlang-cookie", required_argument, 0, "set erlang cookie", uwsgi_opt_set_str, &uerl.cookie, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
|
||||
@@ -94,8 +94,9 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
char *call;
|
||||
char buffer[0xffff];
|
||||
|
||||
char *argv[0xff] ;
|
||||
int argc;
|
||||
char *argv[256] ;
|
||||
uint16_t argvs[256] ;
|
||||
int argc = 0;
|
||||
uint16_t ret;
|
||||
ei_x_buff xr;
|
||||
|
||||
@@ -103,19 +104,20 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("%d %c %c %c\n", etype, etype, ERL_SMALL_TUPLE_EXT, ERL_LARGE_TUPLE_EXT);
|
||||
#endif
|
||||
if (etype != ERL_SMALL_TUPLE_EXT && etype != ERL_LARGE_TUPLE_EXT) return;
|
||||
|
||||
uwsgi_log("decode tuple\n");
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("rpc arity %d\n", arity);
|
||||
#endif
|
||||
if (arity != 3) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
gen_call = uwsgi_malloc(esize);
|
||||
@@ -127,7 +129,9 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
ei_decode_string(x->buff, &x->index, gen_call);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("gen call = %s\n", gen_call);
|
||||
#endif
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
@@ -138,13 +142,10 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
ei_skip_term(x->buff, &x->index);
|
||||
uwsgi_log("skip0 %d %c\n", etype, etype);
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("skip1 %d %c\n", etype, etype);
|
||||
ei_decode_ref(x->buff, &x->index, &eref);
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
module = uwsgi_malloc(esize);
|
||||
|
||||
@@ -157,17 +158,16 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
if (etype != ERL_SMALL_TUPLE_EXT) return ;
|
||||
|
||||
ei_decode_tuple_header(x->buff, &x->index, &arity);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("arity: %d\n", arity);
|
||||
#endif
|
||||
if (arity != 5) return ;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
char *method = uwsgi_malloc(esize);
|
||||
|
||||
@@ -181,7 +181,6 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
if (strcmp(method, "call")) return;
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
uwsgi_log("%d %c\n", etype, etype);
|
||||
|
||||
if (etype != ERL_ATOM_EXT && etype != ERL_STRING_EXT) return ;
|
||||
|
||||
@@ -207,7 +206,9 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
ei_decode_string(x->buff, &x->index, call);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("RPC %s %s\n", module, call);
|
||||
#endif
|
||||
|
||||
ei_get_type(x->buff, &x->index, &etype, &esize);
|
||||
|
||||
@@ -215,16 +216,20 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
argc = 1;
|
||||
argv[0] = uwsgi_malloc(esize+1);
|
||||
ei_decode_atom(x->buff, &x->index, argv[0]);
|
||||
argvs[1] = esize;
|
||||
}
|
||||
else if (etype == ERL_STRING_EXT) {
|
||||
argc = 1;
|
||||
argv[0] = uwsgi_malloc(esize+1);
|
||||
ei_decode_string(x->buff, &x->index, argv[0]);
|
||||
argvs[1] = esize;
|
||||
}
|
||||
|
||||
ret = uwsgi_rpc(call, argc, argv, buffer);
|
||||
ret = uwsgi_rpc(call, argc, argv, argvs, buffer);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("buffer: %.*s\n", ret, buffer);
|
||||
#endif
|
||||
|
||||
ei_x_new_with_version(&xr);
|
||||
|
||||
@@ -239,7 +244,7 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
|
||||
|
||||
}
|
||||
|
||||
void erlang_loop() {
|
||||
void erlang_loop(int id) {
|
||||
|
||||
ErlConnect econn;
|
||||
//ErlMessage em;
|
||||
@@ -247,7 +252,6 @@ void erlang_loop() {
|
||||
int fd;
|
||||
|
||||
int eversion;
|
||||
int i;
|
||||
|
||||
ei_x_buff x, xr;
|
||||
|
||||
@@ -286,7 +290,7 @@ void erlang_loop() {
|
||||
if (em.msgtype == ERL_TICK)
|
||||
continue;
|
||||
|
||||
uwsgi_log("From: %s To: %s RegName: %s\n", em.from.node, em.to.node, em.toname);
|
||||
uwsgi_log("[erlang] message From: %s To (process): %s\n", em.from.node, em.toname);
|
||||
|
||||
|
||||
|
||||
@@ -300,20 +304,18 @@ void erlang_loop() {
|
||||
uwsgi_erlang_rpc(fd, &em.from, &x);
|
||||
}
|
||||
else {
|
||||
int uep = -1;
|
||||
for(i=0;i<uerl.uep_cnt;i++) {
|
||||
if (!strcmp(uerl.uep[i].name, em.toname)) {
|
||||
uep = i;
|
||||
struct uwsgi_erlang_process *uep = uerl.uep;
|
||||
while(uep) {
|
||||
if (!strcmp(uep->name, em.toname)) {
|
||||
if (uep->plugin) {
|
||||
uep->plugin(uep->func, &x);
|
||||
}
|
||||
break;
|
||||
}
|
||||
uep = uep->next;
|
||||
}
|
||||
|
||||
if (uep > -1) {
|
||||
if (uerl.uep[uep].plugin) {
|
||||
uerl.uep[uep].plugin( uerl.uep[uep].func, &x );
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (!uep) {
|
||||
uwsgi_log("!!! unregistered erlang process requested, dumping it !!!\n");
|
||||
dump_eterm(&x);
|
||||
}
|
||||
@@ -361,12 +363,10 @@ int erlang_init() {
|
||||
char *nodename;
|
||||
struct in_addr addr;
|
||||
|
||||
uerl.lock = uwsgi_mmap_shared_lock();
|
||||
uwsgi_lock_init(uerl.lock);
|
||||
uerl.lock = uwsgi_lock_init("erlang");
|
||||
|
||||
if (uerl.name) {
|
||||
|
||||
uwsgi.master_process = 1;
|
||||
|
||||
host = strchr(uerl.name, '@');
|
||||
|
||||
@@ -422,34 +422,20 @@ int erlang_init() {
|
||||
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
|
||||
|
||||
|
||||
if (register_fat_gateway("erlang", erlang_loop) == NULL) {
|
||||
if (register_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
|
||||
uwsgi_log("unable to register the erlang gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int erlang_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_ERLANG:
|
||||
uerl.name = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_ERLANG_COOKIE:
|
||||
uerl.cookie = optarg;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin erlang_plugin = {
|
||||
|
||||
.name = "erlang",
|
||||
.options = erlang_options,
|
||||
.manage_opt = erlang_opt,
|
||||
.init = erlang_init,
|
||||
};
|
||||
|
||||
|
||||
@@ -1,17 +1,12 @@
|
||||
#include <ei.h>
|
||||
|
||||
#define MAX_UWSGI_ERLANG_PROCESSES 64
|
||||
|
||||
#define LONG_ARGS_ERLANG 17012
|
||||
#define LONG_ARGS_ERLANG_COOKIE 17013
|
||||
|
||||
|
||||
|
||||
struct uwsgi_erlang_process {
|
||||
|
||||
char name[0xff];
|
||||
void (*plugin)(void *, ei_x_buff *);
|
||||
void *func;
|
||||
|
||||
struct uwsgi_erlang_process *next;
|
||||
};
|
||||
|
||||
struct uwsgi_erlang {
|
||||
@@ -24,7 +19,6 @@ struct uwsgi_erlang {
|
||||
|
||||
void *lock;
|
||||
|
||||
struct uwsgi_erlang_process uep[MAX_UWSGI_ERLANG_PROCESSES];
|
||||
int uep_cnt;
|
||||
struct uwsgi_erlang_process *uep;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,15 @@
|
||||
import os
|
||||
|
||||
NAME='erlang'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
|
||||
ERLANGPATH = os.environ.get('UWSGICONFIG_ERLANGPATH', 'erl')
|
||||
|
||||
includedir = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, include)])\" -s erlang halt").read().rstrip()
|
||||
libpath = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, lib)])\" -s erlang halt").read().rstrip()
|
||||
|
||||
CFLAGS = [ '-I' + includedir ]
|
||||
LDFLAGS = [ '-L' + libpath ]
|
||||
|
||||
LIBS = ['-lei']
|
||||
|
||||
GCC_LIST = ['erlang']
|
||||
|
||||
+637
-547
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,164 @@
|
||||
#define FASTROUTER_STATUS_FREE 0
|
||||
#define FASTROUTER_STATUS_CONNECTING 1
|
||||
#define FASTROUTER_STATUS_RECV_HDR 2
|
||||
#define FASTROUTER_STATUS_RECV_VARS 3
|
||||
#define FASTROUTER_STATUS_RESPONSE 4
|
||||
#define FASTROUTER_STATUS_BUFFERING 5
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
#define FASTROUTER_STATUS_SCTP_NODE_FREE 6
|
||||
#define FASTROUTER_STATUS_SCTP_RESPONSE 7
|
||||
#endif
|
||||
|
||||
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
|
||||
#define add_fake_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+1, x)
|
||||
#define add_check_timeout(x) uwsgi_add_rb_timer(timeouts, time(NULL)+x, NULL)
|
||||
#define del_check_timeout(x) rb_erase(&x->rbt, timeouts);
|
||||
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
|
||||
|
||||
struct fastrouter_session;
|
||||
|
||||
struct uwsgi_fastrouter {
|
||||
|
||||
int (*mapper)(struct fastrouter_session *, char **);
|
||||
|
||||
int has_sockets;
|
||||
int has_subscription_sockets;
|
||||
#ifdef UWSGI_SCTP
|
||||
int has_sctp_sockets;
|
||||
#endif
|
||||
|
||||
int processes;
|
||||
int quiet;
|
||||
|
||||
struct rb_root *timeouts;
|
||||
|
||||
int use_cache;
|
||||
int nevents;
|
||||
|
||||
char *magic_table[0xff];
|
||||
|
||||
int queue;
|
||||
|
||||
char *pattern;
|
||||
int pattern_len;
|
||||
|
||||
char *base;
|
||||
int base_len;
|
||||
|
||||
size_t post_buffering;
|
||||
char *pb_base_dir;
|
||||
|
||||
struct uwsgi_string_list *static_nodes;
|
||||
struct uwsgi_string_list *current_static_node;
|
||||
int static_node_gracetime;
|
||||
|
||||
char *stats_server;
|
||||
int fr_stats_server;
|
||||
|
||||
int use_socket;
|
||||
int socket_num;
|
||||
struct uwsgi_socket *to_socket;
|
||||
|
||||
struct uwsgi_subscribe_slot *subscriptions;
|
||||
int subscription_regexp;
|
||||
|
||||
struct uwsgi_string_list *fallback;
|
||||
|
||||
int socket_timeout;
|
||||
|
||||
uint8_t code_string_modifier1;
|
||||
char *code_string_code;
|
||||
char *code_string_function;
|
||||
|
||||
|
||||
struct uwsgi_rb_timer *subscriptions_check;
|
||||
|
||||
int cheap;
|
||||
int i_am_cheap;
|
||||
|
||||
int tolerance;
|
||||
int harakiri;
|
||||
|
||||
struct fastrouter_session **fr_table;
|
||||
|
||||
};
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
struct uwsgi_fr_sctp_node {
|
||||
|
||||
int fd;
|
||||
char name[64];
|
||||
uint64_t requests;
|
||||
struct uwsgi_fr_sctp_node *prev;
|
||||
struct uwsgi_fr_sctp_node *next;
|
||||
};
|
||||
|
||||
struct uwsgi_fr_sctp_node *uwsgi_fr_sctp_add_node(int);
|
||||
void uwsgi_fr_sctp_del_node(int);
|
||||
void uwsgi_opt_fastrouter_sctp(char *, char *, void *);
|
||||
|
||||
#endif
|
||||
|
||||
struct fastrouter_session {
|
||||
|
||||
int fd;
|
||||
int instance_fd;
|
||||
int status;
|
||||
struct uwsgi_header uh;
|
||||
uint8_t h_pos;
|
||||
uint16_t pos;
|
||||
|
||||
char *hostname;
|
||||
uint16_t hostname_len;
|
||||
|
||||
int has_key;
|
||||
int retry;
|
||||
#ifdef UWSGI_SCTP
|
||||
int persistent;
|
||||
#endif
|
||||
|
||||
char *instance_address;
|
||||
uint64_t instance_address_len;
|
||||
|
||||
struct uwsgi_subscribe_node *un;
|
||||
struct uwsgi_string_list *static_node;
|
||||
int pass_fd;
|
||||
int soopt;
|
||||
int timed_out;
|
||||
|
||||
struct uwsgi_rb_timer *timeout;
|
||||
int instance_failed;
|
||||
|
||||
size_t post_cl;
|
||||
size_t post_remains;
|
||||
|
||||
struct uwsgi_string_list *fallback;
|
||||
|
||||
char *buf_file_name;
|
||||
FILE *buf_file;
|
||||
|
||||
uint8_t modifier1;
|
||||
uint8_t modifier2;
|
||||
|
||||
char *tmp_socket_name;
|
||||
|
||||
char buffer[0xffff];
|
||||
};
|
||||
|
||||
|
||||
void uwsgi_fastrouter_switch_events(struct fastrouter_session *, int intersting_fd, char **);
|
||||
void close_session(struct fastrouter_session *);
|
||||
void fr_get_hostname(char *, uint16_t, char *, uint16_t, void *);
|
||||
|
||||
int uwsgi_fr_map_use_void(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_cache(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_pattern(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_subscription(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_base(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_cs(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_to(struct fastrouter_session *, char **);
|
||||
int uwsgi_fr_map_use_static_nodes(struct fastrouter_session *, char **);
|
||||
#ifdef UWSGI_SCTP
|
||||
int uwsgi_fr_map_use_sctp(struct fastrouter_session *, char **);
|
||||
#endif
|
||||
@@ -0,0 +1,428 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include "fr.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_fastrouter ufr;
|
||||
|
||||
void uwsgi_fastrouter_switch_events(struct fastrouter_session *fr_session, int interesting_fd, char **magic_table) {
|
||||
|
||||
socklen_t solen = sizeof(int);
|
||||
struct iovec iov[2];
|
||||
|
||||
struct msghdr msg;
|
||||
union {
|
||||
struct cmsghdr cmsg;
|
||||
char control[CMSG_SPACE(sizeof(int))];
|
||||
} msg_control;
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
ssize_t len;
|
||||
char *post_tmp_buf[0xffff];
|
||||
|
||||
switch (fr_session->status) {
|
||||
|
||||
case FASTROUTER_STATUS_RECV_HDR:
|
||||
len = recv(fr_session->fd, (char *) (&fr_session->uh) + fr_session->h_pos, 4 - fr_session->h_pos, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
fr_session->h_pos += len;
|
||||
if (fr_session->h_pos == 4) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("modifier1: %d pktsize: %d modifier2: %d\n", fr_session->uh.modifier1, fr_session->uh.pktsize, fr_session->uh.modifier2);
|
||||
#endif
|
||||
fr_session->status = FASTROUTER_STATUS_RECV_VARS;
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case FASTROUTER_STATUS_RECV_VARS:
|
||||
|
||||
if (interesting_fd == -1) {
|
||||
goto choose_node;
|
||||
}
|
||||
|
||||
len = recv(fr_session->fd, fr_session->buffer + fr_session->pos, fr_session->uh.pktsize - fr_session->pos, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
fr_session->pos += len;
|
||||
if (fr_session->pos == fr_session->uh.pktsize) {
|
||||
if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fr_session->hostname_len == 0) {
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
|
||||
#endif
|
||||
|
||||
// the mapper hook
|
||||
choose_node:
|
||||
if (ufr.mapper(fr_session, magic_table))
|
||||
break;
|
||||
|
||||
// no address found
|
||||
if (!fr_session->instance_address_len) {
|
||||
// if fallback nodes are configured, trigger them
|
||||
if (ufr.fallback) {
|
||||
fr_session->instance_failed = 1;
|
||||
}
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ufr.post_buffering > 0 && fr_session->post_cl > ufr.post_buffering) {
|
||||
fr_session->status = FASTROUTER_STATUS_BUFFERING;
|
||||
fr_session->buf_file_name = uwsgi_tmpname(ufr.pb_base_dir, "uwsgiXXXXX");
|
||||
if (!fr_session->buf_file_name) {
|
||||
uwsgi_error("tempnam()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
fr_session->post_remains = fr_session->post_cl;
|
||||
|
||||
// 2 + UWSGI_POSTFILE + 2 + fr_session->buf_file_name
|
||||
if (fr_session->uh.pktsize + (2 + 14 + 2 + strlen(fr_session->buf_file_name)) > 0xffff) {
|
||||
uwsgi_log("unable to buffer request body to file %s: not enough space\n", fr_session->buf_file_name);
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
char *ptr = fr_session->buffer + fr_session->uh.pktsize;
|
||||
uint16_t bfn_len = strlen(fr_session->buf_file_name);
|
||||
*ptr++ = 14;
|
||||
*ptr++ = 0;
|
||||
memcpy(ptr, "UWSGI_POSTFILE", 14);
|
||||
ptr += 14;
|
||||
*ptr++ = (char) (bfn_len & 0xff);
|
||||
*ptr++ = (char) ((bfn_len >> 8) & 0xff);
|
||||
memcpy(ptr, fr_session->buf_file_name, bfn_len);
|
||||
fr_session->uh.pktsize += 2 + 14 + 2 + bfn_len;
|
||||
|
||||
|
||||
fr_session->buf_file = fopen(fr_session->buf_file_name, "w");
|
||||
if (!fr_session->buf_file) {
|
||||
uwsgi_error_open(fr_session->buf_file_name);
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
|
||||
fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);
|
||||
|
||||
fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);
|
||||
|
||||
if (fr_session->instance_fd < 0) {
|
||||
fr_session->instance_failed = 1;
|
||||
fr_session->soopt = errno;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
fr_session->status = FASTROUTER_STATUS_CONNECTING;
|
||||
ufr.fr_table[fr_session->instance_fd] = fr_session;
|
||||
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
case FASTROUTER_STATUS_CONNECTING:
|
||||
|
||||
if (interesting_fd == fr_session->instance_fd) {
|
||||
|
||||
if (getsockopt(fr_session->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&fr_session->soopt), &solen) < 0) {
|
||||
uwsgi_error("getsockopt()");
|
||||
fr_session->instance_failed = 1;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fr_session->soopt) {
|
||||
fr_session->instance_failed = 1;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
fr_session->uh.modifier1 = fr_session->modifier1;
|
||||
|
||||
iov[0].iov_base = &fr_session->uh;
|
||||
iov[0].iov_len = 4;
|
||||
iov[1].iov_base = fr_session->buffer;
|
||||
iov[1].iov_len = fr_session->uh.pktsize;
|
||||
|
||||
// increment node requests counter
|
||||
if (fr_session->un)
|
||||
fr_session->un->requests++;
|
||||
|
||||
// fd passing: PERFORMANCE EXTREME BOOST !!!
|
||||
if (fr_session->pass_fd && !uwsgi.no_fd_passing) {
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = iov;
|
||||
msg.msg_iovlen = 2;
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_control = &msg_control;
|
||||
msg.msg_controllen = sizeof(msg_control);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
memcpy(CMSG_DATA(cmsg), &fr_session->fd, sizeof(int));
|
||||
|
||||
if (sendmsg(fr_session->instance_fd, &msg, 0) < 0) {
|
||||
uwsgi_error("sendmsg()");
|
||||
}
|
||||
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (writev(fr_session->instance_fd, iov, 2) < 0) {
|
||||
uwsgi_error("writev()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
event_queue_fd_write_to_read(ufr.queue, fr_session->instance_fd);
|
||||
fr_session->status = FASTROUTER_STATUS_RESPONSE;
|
||||
}
|
||||
|
||||
break;
|
||||
#ifdef UWSGI_SCTP
|
||||
case FASTROUTER_STATUS_SCTP_NODE_FREE:
|
||||
|
||||
{
|
||||
struct sctp_sndrcvinfo sinfo;
|
||||
int msg_flags = 0;
|
||||
|
||||
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
len = sctp_recvmsg(interesting_fd, fr_session->buffer, 0xffff, NULL, NULL, &sinfo, &msg_flags);
|
||||
// remove the SCTP node
|
||||
uwsgi_log("[0] removing SCTP node %d flags = %d len = %d\n", interesting_fd, msg_flags, len);
|
||||
uwsgi_fr_sctp_del_node(interesting_fd);
|
||||
if (ufr.fr_table[interesting_fd]->timeout) {
|
||||
del_timeout(ufr.fr_table[interesting_fd]);
|
||||
}
|
||||
free(ufr.fr_table[interesting_fd]);
|
||||
ufr.fr_table[interesting_fd] = NULL;
|
||||
close(interesting_fd);
|
||||
}
|
||||
|
||||
break;
|
||||
case FASTROUTER_STATUS_SCTP_RESPONSE:
|
||||
|
||||
// data from instance
|
||||
if (interesting_fd == fr_session->instance_fd) {
|
||||
struct sctp_sndrcvinfo sinfo;
|
||||
struct uwsgi_header *uh;
|
||||
int msg_flags = 0;
|
||||
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
len = sctp_recvmsg(fr_session->instance_fd, fr_session->buffer, 0xffff, NULL, NULL, &sinfo, &msg_flags);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(ufr.fr_table[fr_session->fd]);
|
||||
// REMOVE THE NODE
|
||||
uwsgi_log("[1] removing SCTP node %d flags = %d len = %d\n", interesting_fd, msg_flags, len);
|
||||
uwsgi_fr_sctp_del_node(interesting_fd);
|
||||
if (ufr.fr_table[interesting_fd]->timeout) {
|
||||
del_timeout(ufr.fr_table[interesting_fd]);
|
||||
}
|
||||
free(ufr.fr_table[interesting_fd]);
|
||||
ufr.fr_table[interesting_fd] = NULL;
|
||||
close(interesting_fd);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
if (fr_session->fd != -1 && sinfo.sinfo_stream != fr_session->fd) {
|
||||
if (fr_session->fd != -1) {
|
||||
uwsgi_log("INVALID SCTP STREAM !!!\n");
|
||||
close_session(ufr.fr_table[fr_session->fd]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
uh = (struct uwsgi_header *) &sinfo.sinfo_ppid;
|
||||
|
||||
// check for close packet
|
||||
if (uh->modifier1 == 200) {
|
||||
fr_session->status = FASTROUTER_STATUS_SCTP_NODE_FREE;
|
||||
if (fr_session->fd != -1) {
|
||||
close_session(ufr.fr_table[fr_session->fd]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (fr_session->fd == -1) {
|
||||
break;
|
||||
}
|
||||
|
||||
len = send(fr_session->fd, fr_session->buffer, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
close_session(ufr.fr_table[fr_session->fd]);
|
||||
break;
|
||||
}
|
||||
|
||||
// update transfer statistics
|
||||
if (fr_session->un)
|
||||
fr_session->un->transferred += len;
|
||||
|
||||
}
|
||||
// body from client
|
||||
else if (interesting_fd == fr_session->fd) {
|
||||
|
||||
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
// mark session as broken
|
||||
ufr.fr_table[fr_session->instance_fd]->fd = -1;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
struct sctp_sndrcvinfo sinfo;
|
||||
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
// map the stream id to the file descriptor
|
||||
struct uwsgi_header uh;
|
||||
uh.modifier1 = 199;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = 0;
|
||||
memcpy(&sinfo.sinfo_ppid, &uh, sizeof(uint32_t));
|
||||
sinfo.sinfo_stream = fr_session->fd;
|
||||
|
||||
len = sctp_send(fr_session->instance_fd, fr_session->buffer, len, &sinfo, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
#endif
|
||||
case FASTROUTER_STATUS_RESPONSE:
|
||||
|
||||
// data from instance
|
||||
if (interesting_fd == fr_session->instance_fd) {
|
||||
len = recv(fr_session->instance_fd, fr_session->buffer, 0xffff, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
len = send(fr_session->fd, fr_session->buffer, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
// update transfer statistics
|
||||
if (fr_session->un)
|
||||
fr_session->un->transferred += len;
|
||||
}
|
||||
// body from client
|
||||
else if (interesting_fd == fr_session->fd) {
|
||||
|
||||
//uwsgi_log("receiving body...\n");
|
||||
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
len = send(fr_session->instance_fd, fr_session->buffer, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("send()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case FASTROUTER_STATUS_BUFFERING:
|
||||
len = recv(fr_session->fd, post_tmp_buf, UMIN(0xffff, fr_session->post_remains), 0);
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
uwsgi_error("recv()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
if (fwrite(post_tmp_buf, len, 1, fr_session->buf_file) != 1) {
|
||||
uwsgi_error("fwrite()");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
fr_session->post_remains -= len;
|
||||
|
||||
if (fr_session->post_remains == 0) {
|
||||
// close the buf_file ASAP
|
||||
fclose(fr_session->buf_file);
|
||||
fr_session->buf_file = NULL;
|
||||
|
||||
fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);
|
||||
|
||||
fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);
|
||||
|
||||
if (fr_session->instance_fd < 0) {
|
||||
fr_session->instance_failed = 1;
|
||||
close_session(fr_session);
|
||||
break;
|
||||
}
|
||||
|
||||
fr_session->status = FASTROUTER_STATUS_CONNECTING;
|
||||
ufr.fr_table[fr_session->instance_fd] = fr_session;
|
||||
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
|
||||
|
||||
// fallback to destroy !!!
|
||||
default:
|
||||
uwsgi_log("unknown event: closing session\n");
|
||||
close_session(fr_session);
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include "fr.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_fastrouter ufr;
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
extern struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes;
|
||||
extern struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes_current;
|
||||
#endif
|
||||
|
||||
|
||||
int uwsgi_fr_map_use_void(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_cache(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
|
||||
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
|
||||
if (cs_mod) {
|
||||
fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
|
||||
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_pattern(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
int tmp_socket_name_len = 0;
|
||||
magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);
|
||||
fr_session->tmp_socket_name = magic_sub(ufr.pattern, ufr.pattern_len, &tmp_socket_name_len, magic_table);
|
||||
free(magic_table['s']);
|
||||
fr_session->instance_address_len = tmp_socket_name_len;
|
||||
fr_session->instance_address = fr_session->tmp_socket_name;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_fr_map_use_subscription(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
|
||||
fr_session->un = uwsgi_get_subscribe_node(&ufr.subscriptions, fr_session->hostname, fr_session->hostname_len, ufr.subscription_regexp);
|
||||
if (fr_session->un && fr_session->un->len) {
|
||||
fr_session->instance_address = fr_session->un->name;
|
||||
fr_session->instance_address_len = fr_session->un->len;
|
||||
fr_session->modifier1 = fr_session->un->modifier1;
|
||||
}
|
||||
else if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
|
||||
uwsgi_gateway_go_cheap("uWSGI fastrouter", ufr.queue, &ufr.i_am_cheap);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_base(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
|
||||
int tmp_socket_name_len = 0;
|
||||
|
||||
fr_session->tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
|
||||
fr_session->instance_address_len = tmp_socket_name_len;
|
||||
fr_session->instance_address = fr_session->tmp_socket_name;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_fr_map_use_cs(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
|
||||
fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
|
||||
if (fr_session->instance_address) {
|
||||
fr_session->instance_address_len = strlen(fr_session->instance_address);
|
||||
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
|
||||
if (cs_mod) {
|
||||
fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
|
||||
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_to(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
fr_session->instance_address = ufr.to_socket->name;
|
||||
fr_session->instance_address_len = ufr.to_socket->name_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_fr_map_use_static_nodes(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
if (!ufr.current_static_node) {
|
||||
ufr.current_static_node = ufr.static_nodes;
|
||||
}
|
||||
|
||||
fr_session->static_node = ufr.current_static_node;
|
||||
|
||||
// is it a dead node ?
|
||||
if (fr_session->static_node->custom > 0) {
|
||||
|
||||
// gracetime passed ?
|
||||
if (fr_session->static_node->custom + ufr.static_node_gracetime <= (uint64_t) uwsgi_now()) {
|
||||
fr_session->static_node->custom = 0;
|
||||
}
|
||||
else {
|
||||
struct uwsgi_string_list *tmp_node = fr_session->static_node;
|
||||
struct uwsgi_string_list *next_node = fr_session->static_node->next;
|
||||
fr_session->static_node = NULL;
|
||||
// needed for 1-node only setups
|
||||
if (!next_node)
|
||||
next_node = ufr.static_nodes;
|
||||
|
||||
while (tmp_node != next_node) {
|
||||
if (!next_node) {
|
||||
next_node = ufr.static_nodes;
|
||||
}
|
||||
|
||||
if (tmp_node == next_node)
|
||||
break;
|
||||
|
||||
if (next_node->custom == 0) {
|
||||
fr_session->static_node = next_node;
|
||||
break;
|
||||
}
|
||||
next_node = next_node->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (fr_session->static_node) {
|
||||
|
||||
fr_session->instance_address = fr_session->static_node->value;
|
||||
fr_session->instance_address_len = fr_session->static_node->len;
|
||||
// set the next one
|
||||
ufr.current_static_node = fr_session->static_node->next;
|
||||
}
|
||||
else {
|
||||
// set the next one
|
||||
ufr.current_static_node = ufr.current_static_node->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SCTP
|
||||
|
||||
int uwsgi_fr_map_use_sctp(struct fastrouter_session *fr_session, char **magic_table) {
|
||||
|
||||
if (!*uwsgi_fastrouter_sctp_nodes_current)
|
||||
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
|
||||
|
||||
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes_current;
|
||||
int choosen_fd = -1;
|
||||
// find the first available server
|
||||
while (ufsn) {
|
||||
if (ufr.fr_table[ufsn->fd]->status == FASTROUTER_STATUS_SCTP_NODE_FREE) {
|
||||
ufsn->requests++;
|
||||
choosen_fd = ufsn->fd;
|
||||
break;
|
||||
}
|
||||
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes_current) {
|
||||
break;
|
||||
}
|
||||
|
||||
ufsn = ufsn->next;
|
||||
}
|
||||
|
||||
// no nodes available
|
||||
if (choosen_fd == -1) {
|
||||
fr_session->retry = 1;
|
||||
del_timeout(fr_session);
|
||||
fr_session->timeout = add_fake_timeout(fr_session);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sctp_sndrcvinfo sinfo;
|
||||
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
|
||||
memcpy(&sinfo.sinfo_ppid, &fr_session->uh, sizeof(uint32_t));
|
||||
sinfo.sinfo_stream = fr_session->fd;
|
||||
ssize_t len = sctp_send(choosen_fd, fr_session->buffer, fr_session->uh.pktsize, &sinfo, 0);
|
||||
if (len < 0)
|
||||
uwsgi_error("sctp_send()");
|
||||
|
||||
fr_session->instance_fd = choosen_fd;
|
||||
fr_session->status = FASTROUTER_STATUS_SCTP_RESPONSE;
|
||||
ufr.fr_table[fr_session->instance_fd]->status = FASTROUTER_STATUS_SCTP_RESPONSE;
|
||||
ufr.fr_table[fr_session->instance_fd]->fd = fr_session->fd;
|
||||
|
||||
// round robin
|
||||
*uwsgi_fastrouter_sctp_nodes_current = (*uwsgi_fastrouter_sctp_nodes_current)->next;
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifdef UWSGI_SCTP
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
#include "fr.h"
|
||||
|
||||
extern struct uwsgi_fastrouter ufr;
|
||||
|
||||
struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes;
|
||||
struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes_current;
|
||||
|
||||
struct uwsgi_fr_sctp_node *uwsgi_fr_sctp_add_node(int fd) {
|
||||
|
||||
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes;
|
||||
|
||||
if (!ufsn) {
|
||||
*uwsgi_fastrouter_sctp_nodes = uwsgi_malloc(sizeof(struct uwsgi_fr_sctp_node));
|
||||
(*uwsgi_fastrouter_sctp_nodes)->next = *uwsgi_fastrouter_sctp_nodes;
|
||||
(*uwsgi_fastrouter_sctp_nodes)->prev = *uwsgi_fastrouter_sctp_nodes;
|
||||
(*uwsgi_fastrouter_sctp_nodes)->requests = 0;
|
||||
(*uwsgi_fastrouter_sctp_nodes)->fd = fd;
|
||||
|
||||
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
|
||||
|
||||
}
|
||||
else {
|
||||
while(ufsn) {
|
||||
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes) {
|
||||
break;
|
||||
}
|
||||
ufsn = ufsn->next;
|
||||
}
|
||||
|
||||
ufsn->next = uwsgi_malloc(sizeof(struct uwsgi_fr_sctp_node));
|
||||
ufsn->next->next = *uwsgi_fastrouter_sctp_nodes;
|
||||
ufsn->next->prev = ufsn;
|
||||
ufsn->next->requests = 0;
|
||||
ufsn->next->fd = fd;
|
||||
|
||||
(*uwsgi_fastrouter_sctp_nodes)->prev = ufsn->next;
|
||||
*uwsgi_fastrouter_sctp_nodes_current = ufsn->next;
|
||||
|
||||
}
|
||||
|
||||
return *uwsgi_fastrouter_sctp_nodes_current;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_fr_sctp_del_node(int fd) {
|
||||
|
||||
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes;
|
||||
while(ufsn) {
|
||||
|
||||
if (ufsn->fd == fd) {
|
||||
|
||||
struct uwsgi_fr_sctp_node *prev = ufsn->prev;
|
||||
struct uwsgi_fr_sctp_node *next = ufsn->next;
|
||||
|
||||
// am i the only node ?
|
||||
if (prev == ufsn) {
|
||||
free(ufsn);
|
||||
*uwsgi_fastrouter_sctp_nodes = NULL;
|
||||
*uwsgi_fastrouter_sctp_nodes_current = NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
prev->next = next;
|
||||
next->prev = prev;
|
||||
|
||||
// am i the first node ?
|
||||
if (ufsn == *uwsgi_fastrouter_sctp_nodes) {
|
||||
*uwsgi_fastrouter_sctp_nodes = next;
|
||||
*uwsgi_fastrouter_sctp_nodes_current = next;
|
||||
free(ufsn);
|
||||
break;
|
||||
}
|
||||
|
||||
if (*uwsgi_fastrouter_sctp_nodes_current == ufsn) {
|
||||
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
|
||||
}
|
||||
|
||||
free(ufsn);
|
||||
break;
|
||||
}
|
||||
|
||||
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes) {
|
||||
break;
|
||||
}
|
||||
|
||||
ufsn = ufsn->next;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_fastrouter_sctp(char *opt, char *value, void *foobar) {
|
||||
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(value, "uWSGI fastrouter");
|
||||
ugs->sctp = 1;
|
||||
ufr.has_sctp_sockets++;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -4,4 +4,4 @@ CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['fastrouter']
|
||||
GCC_LIST = ['fr_sctp', 'fr_map', 'fastrouter', 'fr_events']
|
||||
|
||||
@@ -7,10 +7,6 @@ struct ufib {
|
||||
VALUE *fib;
|
||||
} ufiber;
|
||||
|
||||
struct option fiber_options[] = {
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
VALUE uwsgi_fiber_request() {
|
||||
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
|
||||
@@ -58,14 +54,13 @@ void fiber_loop() {
|
||||
uwsgi.schedule_to_main = fiber_schedule_to_main;
|
||||
uwsgi.schedule_to_req = fiber_schedule_to_req;
|
||||
|
||||
// must run all the rack/ruby plugins without protection
|
||||
ur.unprotected = 1;
|
||||
|
||||
rb_protect(protected_async_loop, 0, &error);
|
||||
|
||||
if (error) {
|
||||
uwsgi_ruby_exception();
|
||||
exit(1);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// never here
|
||||
@@ -81,5 +76,4 @@ struct uwsgi_plugin fiber_plugin = {
|
||||
|
||||
.name = "fiber",
|
||||
.init = fiber_init,
|
||||
.options = fiber_options,
|
||||
};
|
||||
|
||||
@@ -9,6 +9,7 @@ NAME='fiber'
|
||||
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
|
||||
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-DRUBY19')
|
||||
|
||||
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
|
||||
if includedir == 'nil':
|
||||
|
||||
@@ -0,0 +1,349 @@
|
||||
#include "../python/uwsgi_python.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
#define GEVENT_SWITCH PyObject *gswitch = python_call(ugevent.greenlet_switch, ugevent.greenlet_switch_args, 0, NULL); Py_DECREF(gswitch)
|
||||
#define GET_CURRENT_GREENLET python_call(ugevent.get_current, ugevent.get_current_args, 0, NULL)
|
||||
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req
|
||||
#define stop_the_watchers ret = PyObject_CallMethod(timer, "stop", NULL);\
|
||||
if (ret) { Py_DECREF(ret); }\
|
||||
ret = PyObject_CallMethod(watcher, "stop", NULL);\
|
||||
if (ret) { Py_DECREF(ret); }
|
||||
|
||||
struct uwsgi_gevent {
|
||||
PyObject *greenlet_switch;
|
||||
PyObject *greenlet_switch_args;
|
||||
PyObject *get_current;
|
||||
PyObject *get_current_args;
|
||||
PyObject *hub;
|
||||
PyObject *hub_loop;
|
||||
PyObject *spawn;
|
||||
PyObject *greenlet_args;
|
||||
PyObject *signal_args;
|
||||
} ugevent;
|
||||
|
||||
|
||||
struct wsgi_request *uwsgi_gevent_current_wsgi_req(void) {
|
||||
PyObject *current_greenlet = GET_CURRENT_GREENLET;
|
||||
PyObject *py_wsgi_req = PyObject_GetAttrString(current_greenlet, "uwsgi_wsgi_req");
|
||||
return (struct wsgi_request*) PyLong_AsLong(py_wsgi_req);
|
||||
}
|
||||
|
||||
|
||||
|
||||
PyObject *py_uwsgi_gevent_signal_handler(PyObject * self, PyObject * args) {
|
||||
|
||||
int signal_socket;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:uwsgi_gevent_signal_handler", &signal_socket)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uwsgi_receive_signal(signal_socket, "worker", uwsgi.mywid);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// the following twi functions are called whenever an event is available in the signal queue
|
||||
// they both trigger the same function
|
||||
PyObject *py_uwsgi_gevent_signal(PyObject * self, PyObject * args) {
|
||||
|
||||
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.signal_socket));
|
||||
|
||||
// spawn the signal_handler greenlet
|
||||
PyObject *new_gl = python_call(ugevent.spawn, ugevent.signal_args, 0, NULL);
|
||||
Py_DECREF(new_gl);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
// yes copy&paste no-DRY for me :P
|
||||
PyObject *py_uwsgi_gevent_my_signal(PyObject * self, PyObject * args) {
|
||||
|
||||
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.my_signal_socket));
|
||||
|
||||
// spawn the signal_handler greenlet
|
||||
PyObject *new_gl = python_call(ugevent.spawn, ugevent.signal_args, 0, NULL);
|
||||
Py_DECREF(new_gl);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
|
||||
|
||||
|
||||
struct wsgi_request *wsgi_req = find_first_available_wsgi_req();
|
||||
|
||||
if (wsgi_req == NULL) {
|
||||
uwsgi_log("async queue is full !!!\n");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
// fill wsgi_request structure
|
||||
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi.sockets );
|
||||
|
||||
// mark core as used
|
||||
uwsgi.core[wsgi_req->async_id]->in_request = 1;
|
||||
|
||||
gettimeofday(&wsgi_req->start_of_request, NULL);
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
}
|
||||
|
||||
// accept the connection
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi.sockets->fd)) {
|
||||
free_req_queue;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
// hack to easily pass wsgi_req pointer to the greenlet
|
||||
PyTuple_SetItem(ugevent.greenlet_args, 1, PyLong_FromLong((long)wsgi_req));
|
||||
|
||||
// spawn the request greenlet
|
||||
PyObject *new_gl = python_call(ugevent.spawn, ugevent.greenlet_args, 0, NULL);
|
||||
Py_DECREF(new_gl);
|
||||
|
||||
clear:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *uwsgi_gevent_wait(PyObject *watcher, PyObject *timer, PyObject *current) {
|
||||
|
||||
PyObject *ret;
|
||||
|
||||
// start the io watcher
|
||||
ret = PyObject_CallMethod(watcher, "start", "OO", current, watcher);
|
||||
if (!ret) return NULL;
|
||||
Py_DECREF(ret);
|
||||
|
||||
// start the timeout handler
|
||||
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
|
||||
if (!ret) return NULL;
|
||||
Py_DECREF(ret);
|
||||
|
||||
// pass control to the hub
|
||||
return PyObject_CallMethod(ugevent.hub, "switch", NULL);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *ret;
|
||||
PyObject *py_wsgi_req = PyTuple_GetItem(args, 0);
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) PyLong_AsLong(py_wsgi_req);
|
||||
int status ;
|
||||
|
||||
PyObject *current_greenlet = GET_CURRENT_GREENLET;
|
||||
// another hack to retrieve the current wsgi_req;
|
||||
PyObject_SetAttrString(current_greenlet, "uwsgi_wsgi_req", py_wsgi_req);
|
||||
PyObject *greenlet_switch = PyObject_GetAttrString(current_greenlet, "switch");
|
||||
|
||||
// create a watcher for request socket
|
||||
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
|
||||
if (!watcher) goto clear1;
|
||||
|
||||
// a timer to implement timeoit (thanks Denis)
|
||||
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "i", uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
if (!timer) goto clear0;
|
||||
|
||||
for(;;) {
|
||||
// wait for data in the socket
|
||||
PyObject *ret = uwsgi_gevent_wait(watcher, timer, greenlet_switch);
|
||||
if (!ret) goto clear_and_stop;
|
||||
|
||||
// we can safely decref here as watcher and timer has got a +1 for start() method
|
||||
Py_DECREF(ret);
|
||||
if (ret == timer) {
|
||||
uwsgi_log( "timeout. skip request.\n");
|
||||
goto clear_and_stop;
|
||||
}
|
||||
else if (ret == watcher) {
|
||||
status = wsgi_req->socket->proto(wsgi_req);
|
||||
if (status < 0) {
|
||||
goto clear_and_stop;
|
||||
}
|
||||
else if (status == 0) {
|
||||
stop_the_watchers;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("unrecognized gevent event !!!\n");
|
||||
goto clear_and_stop;
|
||||
}
|
||||
|
||||
stop_the_watchers;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
|
||||
if (wsgi_req->async_status <= UWSGI_OK) {
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
// switch after each yield
|
||||
GEVENT_SWITCH;
|
||||
}
|
||||
|
||||
goto clear;
|
||||
|
||||
clear_and_stop:
|
||||
|
||||
stop_the_watchers;
|
||||
|
||||
clear:
|
||||
Py_DECREF(timer);
|
||||
clear0:
|
||||
Py_DECREF(watcher);
|
||||
clear1:
|
||||
Py_DECREF(greenlet_switch);
|
||||
Py_DECREF(current_greenlet);
|
||||
uwsgi_close_request(wsgi_req);
|
||||
|
||||
free_req_queue;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
|
||||
}
|
||||
|
||||
PyMethodDef uwsgi_gevent_main_def[] = { {"uwsgi_gevent_main", py_uwsgi_gevent_main, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_request_def[] = { {"uwsgi_gevent_request", py_uwsgi_gevent_request, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_signal_def[] = { {"uwsgi_gevent_signal", py_uwsgi_gevent_signal, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_my_signal_def[] = { {"uwsgi_gevent_my_signal", py_uwsgi_gevent_my_signal, METH_VARARGS, ""} };
|
||||
PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler", py_uwsgi_gevent_signal_handler, METH_VARARGS, ""} };
|
||||
|
||||
|
||||
void gevent_loop() {
|
||||
|
||||
if (!uwsgi.has_threads && uwsgi.mywid == 1) {
|
||||
uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
|
||||
}
|
||||
|
||||
// get the GIL
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// ..then reset GIL subsystem as noop (gevent IO will take care of it...)
|
||||
up.gil_get = gil_fake_get;
|
||||
up.gil_release = gil_fake_release;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
uwsgi_log("the gevent loop engine requires async mode (--async <n>)\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi.current_wsgi_req = uwsgi_gevent_current_wsgi_req;
|
||||
|
||||
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
|
||||
if (!gevent_dict) uwsgi_pyexit;
|
||||
|
||||
PyObject *gevent_version = PyDict_GetItemString(gevent_dict, "version_info");
|
||||
if (!gevent_version) uwsgi_pyexit;
|
||||
|
||||
if (PyInt_AsLong(PyTuple_GetItem(gevent_version, 0)) < 1) {
|
||||
uwsgi_log("uWSGI requires at least gevent 1.x version\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
|
||||
if (!ugevent.spawn) uwsgi_pyexit;
|
||||
|
||||
ugevent.greenlet_switch = PyDict_GetItemString(gevent_dict, "sleep");
|
||||
if (!ugevent.greenlet_switch) uwsgi_pyexit;
|
||||
|
||||
ugevent.greenlet_switch_args = PyTuple_New(0);
|
||||
Py_INCREF(ugevent.greenlet_switch_args);
|
||||
|
||||
|
||||
PyObject *gevent_get_hub = PyDict_GetItemString(gevent_dict, "get_hub");
|
||||
|
||||
ugevent.hub = python_call(gevent_get_hub, PyTuple_New(0), 0, NULL);
|
||||
if (!ugevent.hub) uwsgi_pyexit;
|
||||
|
||||
ugevent.get_current = PyDict_GetItemString(gevent_dict, "getcurrent");
|
||||
if (!ugevent.get_current) uwsgi_pyexit;
|
||||
|
||||
ugevent.get_current_args = PyTuple_New(0);
|
||||
Py_INCREF(ugevent.get_current_args);
|
||||
|
||||
|
||||
ugevent.hub_loop = PyObject_GetAttrString(ugevent.hub, "loop");
|
||||
if (!ugevent.hub_loop) uwsgi_pyexit;
|
||||
|
||||
// this is the watcher for server socket
|
||||
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi_sock->fd, 1);
|
||||
if (!watcher) uwsgi_pyexit;
|
||||
|
||||
// main greenlet waiting for connection
|
||||
PyObject *uwsgi_gevent_main = PyCFunction_New(uwsgi_gevent_main_def, NULL);
|
||||
Py_INCREF(uwsgi_gevent_main);
|
||||
|
||||
// greenlet to run at each request
|
||||
PyObject *uwsgi_request_greenlet = PyCFunction_New(uwsgi_gevent_request_def, NULL);
|
||||
Py_INCREF(uwsgi_request_greenlet);
|
||||
|
||||
// pre-fill the greenlet args
|
||||
ugevent.greenlet_args = PyTuple_New(2);
|
||||
PyTuple_SetItem(ugevent.greenlet_args, 0, uwsgi_request_greenlet);
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
// and these are the watcher for signal sockets
|
||||
|
||||
PyObject *signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.signal_socket, 1);
|
||||
if (!signal_watcher) uwsgi_pyexit;
|
||||
|
||||
PyObject *my_signal_watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", uwsgi.my_signal_socket, 1);
|
||||
if (!my_signal_watcher) uwsgi_pyexit;
|
||||
|
||||
PyObject *uwsgi_greenlet_signal = PyCFunction_New(uwsgi_gevent_signal_def, NULL);
|
||||
Py_INCREF(uwsgi_greenlet_signal);
|
||||
|
||||
PyObject *uwsgi_greenlet_my_signal = PyCFunction_New(uwsgi_gevent_my_signal_def, NULL);
|
||||
Py_INCREF(uwsgi_greenlet_my_signal);
|
||||
|
||||
PyObject *uwsgi_greenlet_signal_handler = PyCFunction_New(uwsgi_gevent_signal_handler_def, NULL);
|
||||
Py_INCREF(uwsgi_greenlet_signal_handler);
|
||||
|
||||
ugevent.signal_args = PyTuple_New(2);
|
||||
PyTuple_SetItem(ugevent.signal_args, 0, uwsgi_greenlet_signal_handler);
|
||||
|
||||
// start the two signal watchers
|
||||
if (!PyObject_CallMethod(signal_watcher, "start", "O", uwsgi_greenlet_signal)) uwsgi_pyexit;
|
||||
if (!PyObject_CallMethod(my_signal_watcher, "start", "O", uwsgi_greenlet_my_signal)) uwsgi_pyexit;
|
||||
|
||||
}
|
||||
|
||||
// start the main greenlet
|
||||
PyObject_CallMethod(watcher, "start", "O", uwsgi_gevent_main);
|
||||
|
||||
if (!PyObject_CallMethod(ugevent.hub, "join", NULL)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
uwsgi_log("the gevent Hub is no more :(\n");
|
||||
|
||||
}
|
||||
|
||||
int gevent_init() {
|
||||
|
||||
uwsgi_register_loop( (char *) "gevent", gevent_loop);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin gevent_plugin = {
|
||||
|
||||
.name = "gevent",
|
||||
.init = gevent_init,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
from distutils import sysconfig
|
||||
|
||||
NAME='gevent'
|
||||
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['gevent']
|
||||
@@ -0,0 +1,120 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <zlib.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define MAX_GELF 8192
|
||||
|
||||
struct graylog2_config {
|
||||
char *host;
|
||||
char json_buf[MAX_GELF];
|
||||
char escaped_buf[MAX_GELF];
|
||||
size_t escaped_len;
|
||||
char buffer[MAX_GELF];
|
||||
} g2c;
|
||||
|
||||
ssize_t uwsgi_graylog2_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
size_t i;
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
if (!uwsgi.choosen_logger_arg) {
|
||||
uwsgi_log_safe("invalid graylog2 syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (ul->fd < 0) {
|
||||
uwsgi_error_safe("socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_socket_nb(ul->fd);
|
||||
|
||||
char *comma = strchr(uwsgi.choosen_logger_arg, ',');
|
||||
if (!comma) {
|
||||
uwsgi_log_safe("invalid graylog2 syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
g2c.host = comma + 1;
|
||||
|
||||
*comma = 0;
|
||||
|
||||
char *colon = strchr(uwsgi.choosen_logger_arg, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log_safe("invalid graylog2 syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->addr_len = socket_to_in_addr(uwsgi.choosen_logger_arg, colon, 0, &ul->addr.sa_in);
|
||||
|
||||
*comma = ',';
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
g2c.escaped_len = 0;
|
||||
|
||||
int truncated = 0;
|
||||
char *ptr = g2c.escaped_buf;
|
||||
uLongf destLen = MAX_GELF;
|
||||
|
||||
for(i=0;i<len;i++) {
|
||||
if (message[i] == '\\') {
|
||||
*ptr ++= '\\';
|
||||
g2c.escaped_len++;
|
||||
}
|
||||
else if (message[i] == '"') {
|
||||
*ptr ++= '\\';
|
||||
g2c.escaped_len++;
|
||||
}
|
||||
*ptr ++= message[i];
|
||||
g2c.escaped_len++;
|
||||
|
||||
if (!truncated) {
|
||||
if (g2c.escaped_len == 128) {
|
||||
truncated = 1;
|
||||
}
|
||||
else if (g2c.escaped_len > 128) {
|
||||
truncated = 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (truncated) truncated = 128 - (truncated-1);
|
||||
else (truncated = g2c.escaped_len);
|
||||
|
||||
int rlen = snprintf(g2c.json_buf, MAX_GELF, "{ \"version\": \"1.0\", \"host\": \"%s\", \"short_message\": \"%.*s\", \"full_message\": \"%.*s\", \"timestamp\": %d, \"level\": 5, \"facility\": \"uWSGI-%s\" }",
|
||||
g2c.host, truncated, g2c.escaped_buf, (int)g2c.escaped_len, g2c.escaped_buf, (int) time(NULL), UWSGI_VERSION);
|
||||
|
||||
if (rlen > 0) {
|
||||
if (compressBound((uLong) rlen) <= MAX_GELF) {
|
||||
if (compress((Bytef *) g2c.buffer, &destLen, (Bytef *) g2c.json_buf, (uLong) rlen) == Z_OK) {
|
||||
return sendto(ul->fd, g2c.buffer, destLen, 0, (const struct sockaddr *) &ul->addr, ul->addr_len);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_graylog2_register() {
|
||||
uwsgi_register_logger("graylog2", uwsgi_graylog2_logger);
|
||||
}
|
||||
|
||||
int uwsgi_graylog2_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin graylog2_plugin = {
|
||||
|
||||
.name = "graylog2",
|
||||
.on_load = uwsgi_graylog2_register,
|
||||
.init = uwsgi_graylog2_init
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='graylog2'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lz']
|
||||
GCC_LIST = ['graylog2_plugin']
|
||||
@@ -10,9 +10,9 @@ struct ugreenlet {
|
||||
PyGreenlet **gl;
|
||||
} ugl;
|
||||
|
||||
struct option greenlet_options[] = {
|
||||
{"greenlet", no_argument, &ugl.enabled, 1},
|
||||
{ 0, 0, 0, 0 }
|
||||
struct uwsgi_option greenlet_options[] = {
|
||||
{"greenlet", no_argument, 0, "enable greenlet as suspend engine", uwsgi_opt_true, &ugl.enabled, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
|
||||
|
||||
+611
-549
File diff suppressed because it is too large
Load Diff
+1
-8
@@ -1,16 +1,9 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <jni.h>
|
||||
|
||||
#define MAX_CLASSPATH 64
|
||||
|
||||
#define LONG_ARGS_JVM_BASE 17000 + (300 * 100)
|
||||
#define LONG_ARGS_JVM_CLASS LONG_ARGS_JVM_BASE + 1
|
||||
#define LONG_ARGS_JVM_CLASSPATH LONG_ARGS_JVM_BASE + 2
|
||||
|
||||
struct uwsgi_jvm {
|
||||
|
||||
char *classpath[MAX_CLASSPATH];
|
||||
int classpath_cnt;
|
||||
struct uwsgi_string_list *classpath;
|
||||
|
||||
JNIEnv *env;
|
||||
char *class;
|
||||
|
||||
+10
-30
@@ -5,13 +5,15 @@
|
||||
with javap -s -p <class>
|
||||
you can get method signatures
|
||||
|
||||
This plugin is the core for all of the JVM-based ones
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_jvm ujvm;
|
||||
|
||||
struct option uwsgi_jvm_options[] = {
|
||||
{"jvm-main-class", required_argument, 0, LONG_ARGS_JVM_CLASS},
|
||||
{"jvm-classpath", required_argument, 0, LONG_ARGS_JVM_CLASSPATH},
|
||||
struct uwsgi_option uwsgi_jvm_options[] = {
|
||||
{"jvm-main-class", required_argument, 0, "load the specified class", uwsgi_opt_set_str, &ujvm.class, 0},
|
||||
{"jvm-classpath", required_argument, 0, "add the specified directory to the classpath", uwsgi_opt_add_string_list, &ujvm.classpath, 0},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -87,7 +89,6 @@ int jvm_init(void) {
|
||||
JavaVMOption options[1];
|
||||
jmethodID mmid;
|
||||
|
||||
int i;
|
||||
char *old_cp = NULL ;
|
||||
|
||||
|
||||
@@ -97,17 +98,17 @@ int jvm_init(void) {
|
||||
|
||||
options[0].optionString = "-Djava.class.path=.";
|
||||
|
||||
if (ujvm.classpath_cnt > 0) {
|
||||
for(i=0;i<ujvm.classpath_cnt;i++) {
|
||||
struct uwsgi_string_list *cp = ujvm.classpath;
|
||||
while(cp) {
|
||||
if (old_cp) {
|
||||
options[0].optionString = uwsgi_concat3(old_cp, ":", ujvm.classpath[i]);
|
||||
options[0].optionString = uwsgi_concat3(old_cp, ":", cp->value);
|
||||
free(old_cp);
|
||||
}
|
||||
else {
|
||||
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", ujvm.classpath[i]);
|
||||
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", cp->value);
|
||||
}
|
||||
old_cp = options[0].optionString ;
|
||||
}
|
||||
cp = cp->next;
|
||||
}
|
||||
|
||||
vm_args.options = options;
|
||||
@@ -199,32 +200,11 @@ int uwsgi_jvm_strlen2c(jobject obj) {
|
||||
return (*ujvm.env)->GetStringUTFLength(ujvm.env, obj);
|
||||
}
|
||||
|
||||
int uwsgi_jvm_manage_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_JVM_CLASS:
|
||||
ujvm.class = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_JVM_CLASSPATH:
|
||||
if (ujvm.classpath_cnt < MAX_CLASSPATH) {
|
||||
ujvm.classpath[ujvm.classpath_cnt] = optarg;
|
||||
ujvm.classpath_cnt++;
|
||||
}
|
||||
else {
|
||||
uwsgi_log( "you can specify at most %d --jvm-classpath options\n", MAX_CLASSPATH);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin jvm_plugin = {
|
||||
|
||||
.name = "jvm",
|
||||
.init = jvm_init,
|
||||
.options = uwsgi_jvm_options,
|
||||
.manage_opt = uwsgi_jvm_manage_opt,
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ NAME='jvm'
|
||||
# UWSGICONFIG_JVM_INCPATH="/usr/java/include -I /usr/java/include/solaris" UWSGICONFIG_JVM_LIBPATH="/usr/java/jre/lib/i386/" python uwsgiconfig.py --plugin plugins/jvm
|
||||
|
||||
# Ubuntu
|
||||
JVM_INCPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux"
|
||||
JVM_LIBPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/i386/server/"
|
||||
JVM_INCPATH = "/usr/lib/jvm/java-6-openjdk/include/ -I/usr/lib/jvm/java-6-openjdk/include/linux"
|
||||
JVM_LIBPATH = "/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server/"
|
||||
|
||||
try:
|
||||
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
ssize_t uwsgi_socket_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
int family = AF_UNIX;
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
char *comma = strchr(uwsgi.choosen_logger_arg, ',');
|
||||
if (comma) {
|
||||
ul->data = comma+1;
|
||||
*comma = 0;
|
||||
}
|
||||
|
||||
char *colon = strchr(uwsgi.choosen_logger_arg, ':');
|
||||
if (colon) {
|
||||
family = AF_INET;
|
||||
ul->addr_len = socket_to_in_addr(uwsgi.choosen_logger_arg, colon, 0, &ul->addr.sa_in);
|
||||
}
|
||||
else {
|
||||
ul->addr_len = socket_to_un_addr(uwsgi.choosen_logger_arg, &ul->addr.sa_un);
|
||||
}
|
||||
|
||||
ul->fd = socket(family, SOCK_DGRAM, 0);
|
||||
if (ul->fd < 0) {
|
||||
uwsgi_error_safe("socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&ul->msg, 0, sizeof(struct msghdr));
|
||||
|
||||
ul->msg.msg_name = &ul->addr;
|
||||
ul->msg.msg_namelen = ul->addr_len;
|
||||
if (ul->data) {
|
||||
ul->msg.msg_iov = uwsgi_malloc(sizeof(struct iovec) * 2);
|
||||
ul->msg.msg_iov[0].iov_base = ul->data;
|
||||
ul->msg.msg_iov[0].iov_len = strlen(ul->data);
|
||||
ul->msg.msg_iovlen = 2;
|
||||
ul->count = 1;
|
||||
}
|
||||
else {
|
||||
ul->msg.msg_iov = uwsgi_malloc(sizeof(struct iovec));
|
||||
ul->msg.msg_iovlen = 1;
|
||||
}
|
||||
|
||||
if (comma) {
|
||||
*comma = ',' ;
|
||||
}
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
|
||||
ul->msg.msg_iov[ul->count].iov_base = message;
|
||||
ul->msg.msg_iov[ul->count].iov_len = len;
|
||||
|
||||
return sendmsg(ul->fd, &ul->msg, 0);
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_logsocket_register() {
|
||||
uwsgi_register_logger("socket", uwsgi_socket_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logsocket_plugin = {
|
||||
|
||||
.name = "logsocket",
|
||||
.on_load = uwsgi_logsocket_register,
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='logsocket'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['logsocket_plugin']
|
||||
@@ -12,14 +12,11 @@ struct uwsgi_lua {
|
||||
char *filename;
|
||||
} ulua;
|
||||
|
||||
#define LONG_ARGS_LUA_BASE 17000 + (6 * 100)
|
||||
#define LONG_ARGS_LUA LONG_ARGS_LUA_BASE + 1
|
||||
|
||||
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
|
||||
|
||||
struct option uwsgi_lua_options[] = {
|
||||
struct uwsgi_option uwsgi_lua_options[] = {
|
||||
|
||||
{"lua", required_argument, 0, LONG_ARGS_LUA},
|
||||
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
|
||||
|
||||
{0, 0, 0, 0},
|
||||
|
||||
@@ -583,16 +580,6 @@ void uwsgi_lua_after_request(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_lua_manage_options(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_LUA:
|
||||
ulua.filename = optarg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_lua_magic(char *mountpoint, char *lazy) {
|
||||
|
||||
@@ -643,7 +630,6 @@ char *uwsgi_lua_code_string(char *id, char *code, char *func, char *key, uint16_
|
||||
#endif
|
||||
|
||||
if (lua_pcall(L, 1, 1, 0) != 0) {
|
||||
uwsgi_log("CAZZO\n");
|
||||
uwsgi_log("error running function `f': %s",
|
||||
lua_tostring(L, -1));
|
||||
return NULL;
|
||||
@@ -682,7 +668,7 @@ int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
|
||||
|
||||
}
|
||||
|
||||
uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) {
|
||||
uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
|
||||
uint8_t i;
|
||||
const char *sv;
|
||||
@@ -698,7 +684,7 @@ uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, ifunc);
|
||||
|
||||
for(i=0;i<argc;i++) {
|
||||
lua_pushstring(L, argv[i]);
|
||||
lua_pushlstring(L, argv[i], argvs[i]);
|
||||
}
|
||||
|
||||
if (lua_pcall(L, argc, 1, 0) != 0) {
|
||||
@@ -726,7 +712,6 @@ struct uwsgi_plugin lua_plugin = {
|
||||
.modifier1 = 6,
|
||||
.init = uwsgi_lua_init,
|
||||
.options = uwsgi_lua_options,
|
||||
.manage_opt = uwsgi_lua_manage_options,
|
||||
.request = uwsgi_lua_request,
|
||||
.after_request = uwsgi_lua_after_request,
|
||||
.init_apps = uwsgi_lua_app,
|
||||
|
||||
+25
-38
@@ -3,61 +3,61 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
int use_nagios = 0;
|
||||
|
||||
#define LONG_ARGS_NAGIOS 40000
|
||||
struct uwsgi_option nagios_options[] = {
|
||||
|
||||
struct option nagios_options[] = {
|
||||
|
||||
{"nagios", no_argument, 0, LONG_ARGS_NAGIOS},
|
||||
{0, 0, 0, 0},
|
||||
{"nagios", no_argument, 0, "nagios check", uwsgi_opt_true, &use_nagios, UWSGI_OPT_NO_INITIAL},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
|
||||
int nagios() {
|
||||
|
||||
char *tcp_port;
|
||||
struct wsgi_request nagios_req;
|
||||
// connect and send
|
||||
struct uwsgi_header uh;
|
||||
char *buf = NULL;
|
||||
|
||||
if (!use_nagios) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!uwsgi.sockets) {
|
||||
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
|
||||
exit(3);
|
||||
}
|
||||
tcp_port = strchr(uwsgi.sockets->name, ':');
|
||||
if (tcp_port == NULL) {
|
||||
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
|
||||
exit(3);
|
||||
}
|
||||
|
||||
tcp_port[0] = 0;
|
||||
|
||||
int fd = connect_to_tcp(uwsgi.sockets->name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
int fd = uwsgi_connect(uwsgi.sockets->name, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
if (fd < 0) {
|
||||
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
|
||||
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers %s\n", strerror(errno));
|
||||
if (errno == EPERM || errno == EACCES) {
|
||||
exit(3);
|
||||
}
|
||||
exit(2);
|
||||
}
|
||||
nagios_req.uh.modifier1 = UWSGI_MODIFIER_PING;
|
||||
nagios_req.uh.pktsize = 0;
|
||||
nagios_req.uh.modifier2 = 0;
|
||||
if (write(fd, &nagios_req.uh, 4) != 4) {
|
||||
|
||||
uh.modifier1 = UWSGI_MODIFIER_PING;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = 0;
|
||||
if (write(fd, &uh, 4) != 4) {
|
||||
uwsgi_error("write()");
|
||||
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
|
||||
exit(2);
|
||||
}
|
||||
|
||||
nagios_req.poll.fd = fd;
|
||||
nagios_req.poll.events = POLLIN;
|
||||
|
||||
if (!uwsgi_parse_packet(&nagios_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buf);
|
||||
|
||||
if (ret == -2) {
|
||||
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
|
||||
exit(2);
|
||||
}
|
||||
else if (ret == -1) {
|
||||
fprintf(stdout, "UWSGI CRITICAL: error reading response\n");
|
||||
exit(2);
|
||||
}
|
||||
else {
|
||||
if (nagios_req.uh.pktsize > 0) {
|
||||
fprintf(stdout, "UWSGI WARNING: %.*s\n", nagios_req.uh.pktsize, nagios_req.buffer);
|
||||
if (uh.pktsize > 0 && buf) {
|
||||
fprintf(stdout, "UWSGI WARNING: %.*s\n", uh.pktsize, buf);
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
@@ -71,21 +71,8 @@ int nagios() {
|
||||
exit(3);
|
||||
}
|
||||
|
||||
int nagios_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_NAGIOS:
|
||||
uwsgi.no_initial_output = 1;
|
||||
use_nagios = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin nagios_plugin = {
|
||||
|
||||
.options = nagios_options,
|
||||
.manage_opt = nagios_opt,
|
||||
.init = nagios,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
int uwsgi_request_notfound(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct iovec iov[3];
|
||||
|
||||
if (wsgi_req->protocol_len > 0) {
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
}
|
||||
else {
|
||||
iov[0].iov_base = "HTTP/1.0";
|
||||
iov[0].iov_len = 8;
|
||||
}
|
||||
|
||||
iov[1].iov_base = " 404 Not Found\r\n";
|
||||
iov[1].iov_len = 16;
|
||||
|
||||
iov[2].iov_base = "Content-Type: text/plain\r\n\r\n";
|
||||
iov[2].iov_len = 28;
|
||||
|
||||
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, iov, 3);
|
||||
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "Not Found", 9);
|
||||
wsgi_req->status = 404;
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin notfound_plugin = {
|
||||
|
||||
.name = "notfound",
|
||||
.request = uwsgi_request_notfound,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='notfound'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['notfound']
|
||||
@@ -0,0 +1,927 @@
|
||||
#include "php.h"
|
||||
#include "SAPI.h"
|
||||
#include "php_main.h"
|
||||
#include "php_variables.h"
|
||||
|
||||
#include "ext/standard/php_smart_str.h"
|
||||
#include "ext/standard/info.h"
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// http status codes list
|
||||
extern struct http_status_codes hsc[];
|
||||
|
||||
static sapi_module_struct uwsgi_sapi_module;
|
||||
|
||||
struct uwsgi_php {
|
||||
struct uwsgi_string_list *allowed_docroot;
|
||||
struct uwsgi_string_list *allowed_ext;
|
||||
struct uwsgi_string_list *index;
|
||||
struct uwsgi_string_list *set;
|
||||
struct uwsgi_string_list *append_config;
|
||||
char *docroot;
|
||||
char *app;
|
||||
size_t ini_size;
|
||||
int dump_config;
|
||||
char *server_software;
|
||||
size_t server_software_len;
|
||||
} uphp;
|
||||
|
||||
void uwsgi_opt_php_ini(char *opt, char *value, void *foobar) {
|
||||
uwsgi_sapi_module.php_ini_path_override = uwsgi_str(value);
|
||||
uwsgi_sapi_module.php_ini_ignore = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_option uwsgi_php_options[] = {
|
||||
|
||||
{"php-ini", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
|
||||
{"php-config", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
|
||||
{"php-ini-append", required_argument, 0, "set php.ini path (append mode)", uwsgi_opt_add_string_list, &uphp.append_config, 0},
|
||||
{"php-config-append", required_argument, 0, "set php.ini path (append mode)", uwsgi_opt_add_string_list, &uphp.append_config, 0},
|
||||
{"php-set", required_argument, 0, "set a php config directive", uwsgi_opt_add_string_list, &uphp.set, 0},
|
||||
{"php-index", required_argument, 0, "list the php index files", uwsgi_opt_add_string_list, &uphp.index, 0},
|
||||
{"php-docroot", required_argument, 0, "force php DOCUMENT_ROOT", uwsgi_opt_set_str, &uphp.docroot, 0},
|
||||
{"php-allowed-docroot", required_argument, 0, "list the allowed document roots", uwsgi_opt_add_string_list, &uphp.allowed_docroot, 0},
|
||||
{"php-allowed-ext", required_argument, 0, "list the allowed php file extensions", uwsgi_opt_add_string_list, &uphp.allowed_ext, 0},
|
||||
{"php-server-software", required_argument, 0, "force php SERVER_SOFTWARE", uwsgi_opt_set_str, &uphp.server_software, 0},
|
||||
{"php-app", required_argument, 0, "force the php file to run at each request", uwsgi_opt_set_str, &uphp.app, 0},
|
||||
{"php-dump-config", no_argument, 0, "dump php config (if modified via --php-set or append options)", uwsgi_opt_true, &uphp.dump_config, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
void uwsgi_php_redirect_to_slash(struct wsgi_request *wsgi_req) {
|
||||
|
||||
struct iovec iov[6];
|
||||
|
||||
wsgi_req->status = 301;
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
iov[1].iov_base = " 301 Moved Permanently\r\n";
|
||||
iov[1].iov_len = 24;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
|
||||
iov[0].iov_base = "Location: ";
|
||||
iov[0].iov_len = 10;
|
||||
iov[1].iov_base = wsgi_req->path_info;
|
||||
iov[1].iov_len = wsgi_req->path_info_len;
|
||||
iov[2].iov_base = "/";
|
||||
iov[2].iov_len = 1;
|
||||
|
||||
if (wsgi_req->query_string_len > 0) {
|
||||
iov[3].iov_base = "?";
|
||||
iov[3].iov_len = 1;
|
||||
iov[4].iov_base = wsgi_req->query_string;
|
||||
iov[4].iov_len = wsgi_req->query_string_len;
|
||||
iov[5].iov_base = "\r\n\r\n";
|
||||
iov[5].iov_len = 4;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
else {
|
||||
iov[3].iov_base = "\r\n\r\n";
|
||||
iov[3].iov_len = 4;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC)
|
||||
{
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) str, str_length);
|
||||
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) {
|
||||
php_handle_aborted_connection();
|
||||
return -1;
|
||||
}
|
||||
return str_length;
|
||||
}
|
||||
|
||||
void uwsgi_php_404(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 404;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot Found", 61);
|
||||
}
|
||||
|
||||
void uwsgi_php_403(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->status = 403;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nForbidden", 61);
|
||||
|
||||
}
|
||||
|
||||
|
||||
static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
|
||||
{
|
||||
sapi_header_struct *h;
|
||||
zend_llist_position pos;
|
||||
struct iovec iov[6];
|
||||
char status[4];
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
if (SG(request_info).no_headers == 1) {
|
||||
return SAPI_HEADER_SENT_SUCCESSFULLY;
|
||||
}
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
wsgi_req->status = SG(sapi_headers).http_response_code;
|
||||
if (!wsgi_req->status) wsgi_req->status = 200;
|
||||
|
||||
if (!SG(sapi_headers).http_status_line) {
|
||||
|
||||
iov[0].iov_base = wsgi_req->protocol;
|
||||
iov[0].iov_len = wsgi_req->protocol_len;
|
||||
|
||||
|
||||
iov[1].iov_base = " ";
|
||||
iov[1].iov_len = 1;
|
||||
|
||||
uwsgi_num2str2n(wsgi_req->status, status, 4);
|
||||
|
||||
iov[2].iov_base = status;
|
||||
iov[2].iov_len = 3;
|
||||
|
||||
iov[3].iov_base = " ";
|
||||
iov[3].iov_len = 1;
|
||||
|
||||
// get the status code
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
if (!strncmp(http_sc->key, status, 3)) {
|
||||
iov[4].iov_base = (char *) http_sc->message;
|
||||
iov[4].iov_len = http_sc->message_size;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (iov[4].iov_len == 0) {
|
||||
iov[4].iov_base = "Unknown";
|
||||
iov[4].iov_len = 7;
|
||||
}
|
||||
|
||||
iov[5].iov_base = "\r\n";
|
||||
iov[5].iov_len = 2;
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
|
||||
}
|
||||
else {
|
||||
iov[0].iov_base = SG(sapi_headers).http_status_line;
|
||||
iov[0].iov_len = strlen(iov[0].iov_base);
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
}
|
||||
|
||||
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
|
||||
while (h) {
|
||||
iov[0].iov_base = h->header;
|
||||
iov[0].iov_len = h->header_len;
|
||||
iov[1].iov_base = "\r\n";
|
||||
iov[1].iov_len = 2;
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
|
||||
wsgi_req->header_cnt++;
|
||||
h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
|
||||
}
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
|
||||
|
||||
return SAPI_HEADER_SENT_SUCCESSFULLY;
|
||||
}
|
||||
|
||||
static int sapi_uwsgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
|
||||
{
|
||||
uint read_bytes = 0;
|
||||
size_t len;
|
||||
int fd = -1;
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
|
||||
if (wsgi_req->body_as_file) {
|
||||
fd = fileno((FILE *)wsgi_req->async_post);
|
||||
}
|
||||
else if (uwsgi.post_buffering > 0) {
|
||||
if (wsgi_req->post_cl > (size_t) uwsgi.post_buffering) {
|
||||
fd = fileno((FILE *)wsgi_req->async_post);
|
||||
}
|
||||
}
|
||||
else {
|
||||
fd = wsgi_req->poll.fd;
|
||||
}
|
||||
|
||||
|
||||
count_bytes = MIN(count_bytes, wsgi_req->post_cl - SG(read_post_bytes));
|
||||
|
||||
// data in memory
|
||||
if (fd == -1) {
|
||||
if (count_bytes > 0) {
|
||||
memcpy(buffer, wsgi_req->post_buffering_buf + wsgi_req->post_pos, count_bytes);
|
||||
wsgi_req->post_pos += count_bytes;
|
||||
}
|
||||
return count_bytes;
|
||||
}
|
||||
|
||||
while (read_bytes < count_bytes) {
|
||||
len = read(fd, buffer + read_bytes, count_bytes - read_bytes);
|
||||
if (len <= 0) {
|
||||
break;
|
||||
}
|
||||
read_bytes += len;
|
||||
}
|
||||
|
||||
return read_bytes;
|
||||
}
|
||||
|
||||
|
||||
static char *sapi_uwsgi_read_cookies(void)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
|
||||
char *cookie = uwsgi_get_var(wsgi_req, (char *)"HTTP_COOKIE", 11, &len);
|
||||
if (cookie) {
|
||||
return estrndup(cookie, len);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
|
||||
{
|
||||
int i;
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
|
||||
php_import_environment_variables(track_vars_array TSRMLS_CC);
|
||||
|
||||
if (uphp.server_software) {
|
||||
if (!uphp.server_software_len) uphp.server_software_len = strlen(uphp.server_software);
|
||||
php_register_variable_safe("SERVER_SOFTWARE", uphp.server_software, uphp.server_software_len, track_vars_array TSRMLS_CC);
|
||||
}
|
||||
else {
|
||||
php_register_variable_safe("SERVER_SOFTWARE", "uWSGI", 5, track_vars_array TSRMLS_CC);
|
||||
}
|
||||
|
||||
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
|
||||
php_register_variable_safe( estrndup(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
|
||||
wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len,
|
||||
track_vars_array TSRMLS_CC);
|
||||
}
|
||||
|
||||
php_register_variable_safe("PATH_INFO", wsgi_req->path_info, wsgi_req->path_info_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
php_register_variable_safe("SCRIPT_NAME", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
|
||||
php_register_variable_safe("SCRIPT_FILENAME", wsgi_req->file, wsgi_req->file_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
php_register_variable_safe("DOCUMENT_ROOT", wsgi_req->document_root, wsgi_req->document_root_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
if (wsgi_req->path_info_len) {
|
||||
char *path_translated = ecalloc(1, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len + 1);
|
||||
|
||||
memcpy(path_translated, wsgi_req->file, (wsgi_req->file_len - wsgi_req->script_name_len));
|
||||
memcpy(path_translated + (wsgi_req->file_len - wsgi_req->script_name_len), wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
php_register_variable_safe("PATH_TRANSLATED", path_translated, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len , track_vars_array TSRMLS_CC);
|
||||
}
|
||||
else {
|
||||
php_register_variable_safe("PATH_TRANSLATED", "", 0, track_vars_array TSRMLS_CC);
|
||||
}
|
||||
|
||||
php_register_variable_safe("PHP_SELF", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
|
||||
|
||||
|
||||
}
|
||||
|
||||
static sapi_module_struct uwsgi_sapi_module;
|
||||
|
||||
|
||||
|
||||
|
||||
void uwsgi_php_append_config(char *filename) {
|
||||
int file_size = 0;
|
||||
char *file_content = uwsgi_open_and_read(filename, &file_size, 1, NULL);
|
||||
uwsgi_sapi_module.ini_entries = realloc(uwsgi_sapi_module.ini_entries, uphp.ini_size + file_size);
|
||||
memcpy(uwsgi_sapi_module.ini_entries + uphp.ini_size, file_content, file_size);
|
||||
uphp.ini_size += file_size-1;
|
||||
free(file_content);
|
||||
}
|
||||
|
||||
void uwsgi_php_set(char *opt) {
|
||||
|
||||
uwsgi_sapi_module.ini_entries = realloc(uwsgi_sapi_module.ini_entries, uphp.ini_size + strlen(opt)+2);
|
||||
memcpy(uwsgi_sapi_module.ini_entries + uphp.ini_size, opt, strlen(opt));
|
||||
|
||||
uphp.ini_size += strlen(opt)+1;
|
||||
uwsgi_sapi_module.ini_entries[uphp.ini_size-1] = '\n';
|
||||
uwsgi_sapi_module.ini_entries[uphp.ini_size] = 0;
|
||||
}
|
||||
|
||||
// future implementation...
|
||||
PHP_MINIT_FUNCTION(uwsgi_php_minit) {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_version) {
|
||||
RETURN_STRING(UWSGI_VERSION, 1);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_worker_id) {
|
||||
RETURN_LONG(uwsgi.mywid);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_masterpid) {
|
||||
if (uwsgi.master_process) {
|
||||
RETURN_LONG(uwsgi.workers[0].pid);
|
||||
}
|
||||
RETURN_LONG(0);
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_cache_del) {
|
||||
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
|
||||
if (!uwsgi.cache_max_items)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &keylen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, keylen, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_cache_get) {
|
||||
|
||||
char *key = NULL;
|
||||
int keylen = 0;
|
||||
uint64_t valsize;
|
||||
|
||||
if (!uwsgi.cache_max_items)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &keylen) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
char *value = uwsgi_cache_get(key, keylen, &valsize);
|
||||
if (value) {
|
||||
char *ret = estrndup(value, valsize);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_STRING(ret, 0);
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_cache_set) {
|
||||
char *key = NULL;
|
||||
int keylen;
|
||||
char *value = NULL;
|
||||
int vallen;
|
||||
uint64_t expires = 0;
|
||||
|
||||
if (!uwsgi.cache_max_items)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &key, &keylen, &value, &vallen, &expires) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_NULL();
|
||||
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_cache_update) {
|
||||
char *key = NULL;
|
||||
int keylen;
|
||||
char *value = NULL;
|
||||
int vallen;
|
||||
uint64_t expires = 0;
|
||||
|
||||
if (!uwsgi.cache_max_items)
|
||||
RETURN_NULL();
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &key, &keylen, &value, &vallen, &expires) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_TRUE;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
RETURN_NULL();
|
||||
|
||||
}
|
||||
|
||||
|
||||
PHP_FUNCTION(uwsgi_rpc) {
|
||||
|
||||
|
||||
int num_args = 0;
|
||||
int i;
|
||||
char *node = NULL;
|
||||
char *func = NULL;
|
||||
zval ***varargs = NULL;
|
||||
zval *z_current_obj;
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
uint16_t size = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &varargs, &num_args) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
if (num_args < 2)
|
||||
goto clear;
|
||||
|
||||
if (num_args > 256 + 2)
|
||||
goto clear;
|
||||
|
||||
z_current_obj = *varargs[0];
|
||||
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
node = Z_STRVAL_P(z_current_obj);
|
||||
|
||||
z_current_obj = *varargs[1];
|
||||
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
|
||||
goto clear;
|
||||
}
|
||||
|
||||
func = Z_STRVAL_P(z_current_obj);
|
||||
|
||||
for(i=0;i<(num_args-2);i++) {
|
||||
z_current_obj = *varargs[i+2];
|
||||
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
|
||||
goto clear;
|
||||
}
|
||||
argv[i] = Z_STRVAL_P(z_current_obj);
|
||||
argvs[i] = Z_STRLEN_P(z_current_obj);
|
||||
}
|
||||
|
||||
char *response = uwsgi_do_rpc(node, func, num_args - 2, argv, argvs, &size);
|
||||
|
||||
if (size > 0) {
|
||||
// here we do not free varargs for performance reasons
|
||||
char *ret = estrndup(response, size);
|
||||
free(response);
|
||||
RETURN_STRING(ret, 0);
|
||||
}
|
||||
|
||||
clear:
|
||||
efree(varargs);
|
||||
RETURN_NULL();
|
||||
|
||||
}
|
||||
|
||||
|
||||
PHP_FUNCTION(uwsgi_setprocname) {
|
||||
|
||||
char *name;
|
||||
int name_len;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
uwsgi_set_processname(estrndup(name, name_len));
|
||||
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
PHP_FUNCTION(uwsgi_signal) {
|
||||
|
||||
long long_signum;
|
||||
uint8_t signum = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &long_signum) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
signum = (uint8_t) long_signum;
|
||||
uwsgi_signal_send(uwsgi.signal_socket, signum);
|
||||
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
zend_function_entry uwsgi_php_functions[] = {
|
||||
PHP_FE(uwsgi_version, NULL)
|
||||
PHP_FE(uwsgi_setprocname, NULL)
|
||||
PHP_FE(uwsgi_worker_id, NULL)
|
||||
PHP_FE(uwsgi_masterpid, NULL)
|
||||
PHP_FE(uwsgi_signal, NULL)
|
||||
PHP_FE(uwsgi_rpc, NULL)
|
||||
PHP_FE(uwsgi_cache_get, NULL)
|
||||
PHP_FE(uwsgi_cache_set, NULL)
|
||||
PHP_FE(uwsgi_cache_update, NULL)
|
||||
PHP_FE(uwsgi_cache_del, NULL)
|
||||
{ NULL, NULL, NULL},
|
||||
};
|
||||
|
||||
PHP_MINFO_FUNCTION(uwsgi_php_minfo) {
|
||||
php_info_print_table_start( );
|
||||
php_info_print_table_row(2, "uwsgi api", "enabled");
|
||||
if (uwsgi.cache_max_items > 0) {
|
||||
php_info_print_table_row(2, "uwsgi cache", "enabled");
|
||||
}
|
||||
else {
|
||||
php_info_print_table_row(2, "uwsgi cache", "disabled");
|
||||
}
|
||||
php_info_print_table_end( );
|
||||
}
|
||||
|
||||
static zend_module_entry uwsgi_module_entry = {
|
||||
STANDARD_MODULE_HEADER,
|
||||
"uwsgi",
|
||||
uwsgi_php_functions,
|
||||
PHP_MINIT(uwsgi_php_minit),
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
PHP_MINFO(uwsgi_php_minfo),
|
||||
UWSGI_VERSION,
|
||||
STANDARD_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
|
||||
static int php_uwsgi_startup(sapi_module_struct *sapi_module)
|
||||
{
|
||||
|
||||
if (php_module_startup(&uwsgi_sapi_module, &uwsgi_module_entry, 1)==FAILURE) {
|
||||
return FAILURE;
|
||||
} else {
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
static void sapi_uwsgi_log_message(char *message) {
|
||||
|
||||
uwsgi_log("%s\n", message);
|
||||
}
|
||||
|
||||
static sapi_module_struct uwsgi_sapi_module = {
|
||||
"uwsgi",
|
||||
"uWSGI/php",
|
||||
|
||||
php_uwsgi_startup,
|
||||
php_module_shutdown_wrapper,
|
||||
|
||||
NULL, /* activate */
|
||||
NULL, /* deactivate */
|
||||
|
||||
sapi_uwsgi_ub_write,
|
||||
NULL,
|
||||
NULL, /* get uid */
|
||||
NULL, /* getenv */
|
||||
|
||||
php_error,
|
||||
|
||||
NULL,
|
||||
sapi_uwsgi_send_headers,
|
||||
NULL,
|
||||
sapi_uwsgi_read_post,
|
||||
sapi_uwsgi_read_cookies,
|
||||
|
||||
sapi_uwsgi_register_variables,
|
||||
sapi_uwsgi_log_message, /* Log message */
|
||||
NULL, /* Get request time */
|
||||
NULL, /* Child terminate */
|
||||
|
||||
STANDARD_SAPI_MODULE_PROPERTIES
|
||||
};
|
||||
|
||||
int uwsgi_php_init(void) {
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
struct uwsgi_string_list *pset = uphp.set;
|
||||
struct uwsgi_string_list *append_config = uphp.append_config;
|
||||
|
||||
sapi_startup(&uwsgi_sapi_module);
|
||||
|
||||
// applying custom options
|
||||
while(append_config) {
|
||||
uwsgi_php_append_config(append_config->value);
|
||||
append_config = append_config->next;
|
||||
}
|
||||
while(pset) {
|
||||
uwsgi_php_set(pset->value);
|
||||
pset = pset->next;
|
||||
}
|
||||
|
||||
if (uphp.dump_config) {
|
||||
uwsgi_log("--- PHP custom config ---\n\n");
|
||||
uwsgi_log("%s\n", uwsgi_sapi_module.ini_entries);
|
||||
uwsgi_log("--- end of PHP custom config ---\n");
|
||||
}
|
||||
|
||||
uwsgi_sapi_module.startup(&uwsgi_sapi_module);
|
||||
|
||||
// filling http status codes
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
http_sc->message_size = strlen(http_sc->message);
|
||||
}
|
||||
|
||||
uwsgi_log("PHP %s initialized\n", PHP_VERSION);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, char **path_info) {
|
||||
|
||||
// and now start walking...
|
||||
uint16_t i;
|
||||
char *ptr = wsgi_req->path_info;
|
||||
char *dst = full_path+docroot_len;
|
||||
char *part = ptr;
|
||||
int part_size = 0;
|
||||
struct stat st;
|
||||
|
||||
if (wsgi_req->path_info_len == 0) return 0;
|
||||
|
||||
if (ptr[0] == '/') part_size++;
|
||||
|
||||
for(i=0;i<wsgi_req->path_info_len;i++) {
|
||||
if (ptr[i] == '/') {
|
||||
memcpy(dst, part, part_size-1);
|
||||
*(dst+part_size-1) = 0;
|
||||
|
||||
if (stat(full_path, &st)) {
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
// not a directory, stop walking
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
if (i < (wsgi_req->path_info_len)-1) {
|
||||
*path_info = ptr + i;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// check for buffer overflow !!!
|
||||
*(dst+part_size-1) = '/';
|
||||
*(dst+part_size) = 0;
|
||||
|
||||
dst += part_size ;
|
||||
part_size = 0;
|
||||
part = ptr + i + 1;
|
||||
}
|
||||
|
||||
part_size++;
|
||||
}
|
||||
|
||||
if (part < wsgi_req->path_info+wsgi_req->path_info_len) {
|
||||
memcpy(dst, part, part_size-1);
|
||||
*(dst+part_size-1) = 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_php_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char real_filename[PATH_MAX+1];
|
||||
char *path_info = NULL;
|
||||
size_t real_filename_len = 0;
|
||||
struct stat php_stat;
|
||||
|
||||
zend_file_handle file_handle;
|
||||
|
||||
SG(server_context) = (void *) wsgi_req;
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uphp.docroot) {
|
||||
wsgi_req->document_root = uphp.docroot;
|
||||
}
|
||||
// fallback to cwd
|
||||
else if (!wsgi_req->document_root_len) {
|
||||
wsgi_req->document_root = uwsgi.cwd;
|
||||
}
|
||||
else {
|
||||
// explode DOCUMENT_ROOT (both for security and sanity checks)
|
||||
// this memory will be cleared on request end
|
||||
char *sanitized_docroot = ecalloc(1, PATH_MAX+1);
|
||||
if (!uwsgi_expand_path(wsgi_req->document_root, wsgi_req->document_root_len, sanitized_docroot)) {
|
||||
efree(sanitized_docroot);
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->document_root = sanitized_docroot;
|
||||
}
|
||||
|
||||
// fix document_root_len
|
||||
wsgi_req->document_root_len = strlen(wsgi_req->document_root);
|
||||
|
||||
if (uphp.app) {
|
||||
strcpy(real_filename, uphp.app);
|
||||
wsgi_req->path_info = "";
|
||||
wsgi_req->path_info_len = 0;
|
||||
goto secure2;
|
||||
}
|
||||
|
||||
char *filename = uwsgi_concat4n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
|
||||
|
||||
if (uwsgi_php_walk(wsgi_req, filename, wsgi_req->document_root, wsgi_req->document_root_len, &path_info)) {
|
||||
free(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
char *orig_path_info = wsgi_req->path_info;
|
||||
uint16_t orig_path_info_len = wsgi_req->path_info_len;
|
||||
|
||||
if (path_info) {
|
||||
wsgi_req->path_info = path_info;
|
||||
wsgi_req->path_info_len = orig_path_info_len - (path_info - orig_path_info);
|
||||
}
|
||||
else {
|
||||
wsgi_req->path_info = "";
|
||||
wsgi_req->path_info_len = 0;
|
||||
}
|
||||
|
||||
|
||||
if (!realpath(filename, real_filename)) {
|
||||
free(filename);
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(filename);
|
||||
real_filename_len = strlen(real_filename);
|
||||
|
||||
if (uphp.allowed_docroot) {
|
||||
struct uwsgi_string_list *usl = uphp.allowed_docroot;
|
||||
while(usl) {
|
||||
if (!uwsgi_starts_with(real_filename, real_filename_len, usl->value, usl->len)) {
|
||||
goto secure;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_php_403(wsgi_req);
|
||||
uwsgi_log("PHP security error: %s is not under an allowed docroot\n", real_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
secure:
|
||||
|
||||
if (stat(real_filename, &php_stat)) {
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (S_ISDIR(php_stat.st_mode)) {
|
||||
|
||||
// add / to directories
|
||||
if (orig_path_info_len == 0 || (orig_path_info_len > 0 && orig_path_info[orig_path_info_len-1] != '/')) {
|
||||
wsgi_req->path_info = orig_path_info;
|
||||
wsgi_req->path_info_len = orig_path_info_len;
|
||||
uwsgi_php_redirect_to_slash(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
struct uwsgi_string_list *upi = uphp.index;
|
||||
real_filename[real_filename_len] = '/';
|
||||
real_filename_len++;
|
||||
int found = 0;
|
||||
while(upi) {
|
||||
if (real_filename_len + upi->len + 1 < PATH_MAX) {
|
||||
// add + 1 to ensure null byte
|
||||
memcpy(real_filename+real_filename_len, upi->value, upi->len + 1);
|
||||
if (!access(real_filename, R_OK)) {
|
||||
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
upi = upi->next;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
uwsgi_php_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
real_filename_len = strlen(real_filename);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (uphp.allowed_ext) {
|
||||
struct uwsgi_string_list *usl = uphp.allowed_ext;
|
||||
while(usl) {
|
||||
if (real_filename_len >= usl->len) {
|
||||
if (!uwsgi_strncmp(real_filename+(real_filename_len-usl->len), usl->len, usl->value, usl->len)) {
|
||||
goto secure2;
|
||||
}
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
uwsgi_php_403(wsgi_req);
|
||||
uwsgi_log("PHP security error: %s does not end with an allowed extension\n", real_filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
secure2:
|
||||
|
||||
wsgi_req->file = real_filename;
|
||||
wsgi_req->file_len = strlen(wsgi_req->file);
|
||||
|
||||
if (wsgi_req->document_root[wsgi_req->document_root_len-1] == '/') {
|
||||
wsgi_req->script_name = real_filename + (wsgi_req->document_root_len-1);
|
||||
}
|
||||
else {
|
||||
wsgi_req->script_name = real_filename + wsgi_req->document_root_len;
|
||||
}
|
||||
|
||||
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("php filename = %s script_name = %.*s (%d) document_root = %.*s (%d)\n", real_filename, wsgi_req->script_name_len, wsgi_req->script_name, wsgi_req->script_name_len,
|
||||
wsgi_req->document_root_len, wsgi_req->document_root, wsgi_req->document_root_len);
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
// now check for allowed paths and extensions
|
||||
|
||||
SG(request_info).request_uri = estrndup(wsgi_req->uri, wsgi_req->uri_len);
|
||||
SG(request_info).request_method = estrndup(wsgi_req->method, wsgi_req->method_len);
|
||||
SG(request_info).proto_num = 1001;
|
||||
|
||||
SG(request_info).query_string = estrndup(wsgi_req->query_string, wsgi_req->query_string_len);
|
||||
SG(request_info).content_length = wsgi_req->post_cl;
|
||||
SG(request_info).content_type = estrndup(wsgi_req->content_type, wsgi_req->content_type_len);
|
||||
|
||||
// reinitialize it at every request !!!
|
||||
SG(sapi_headers).http_response_code = 200;
|
||||
|
||||
SG(request_info).path_translated = wsgi_req->file;
|
||||
|
||||
file_handle.type = ZEND_HANDLE_FILENAME;
|
||||
file_handle.filename = real_filename;
|
||||
file_handle.free_filename = 0;
|
||||
file_handle.opened_path = NULL;
|
||||
|
||||
if (php_request_startup(TSRMLS_C) == FAILURE) {
|
||||
internal_server_error(wsgi_req, "unable to start php request");
|
||||
return -1;
|
||||
}
|
||||
|
||||
php_execute_script(&file_handle TSRMLS_CC);
|
||||
|
||||
php_request_shutdown(NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_php_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
|
||||
SAPI_API struct uwsgi_plugin php_plugin = {
|
||||
.name = "php",
|
||||
.modifier1 = 14,
|
||||
.init = uwsgi_php_init,
|
||||
.request = uwsgi_php_request,
|
||||
.after_request = uwsgi_php_after_request,
|
||||
.options = uwsgi_php_options,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import os
|
||||
|
||||
NAME='php'
|
||||
|
||||
ld_run_path = None
|
||||
PHPPATH = 'php-config'
|
||||
|
||||
try:
|
||||
phpdir = os.environ['UWSGICONFIG_PHPDIR']
|
||||
ld_run_path = "%s/lib" % phpdir
|
||||
PHPPATH = "%s/bin/php-config" % phpdir
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
PHPPATH = os.environ['UWSGICONFIG_PHPPATH']
|
||||
except:
|
||||
pass
|
||||
|
||||
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip()]
|
||||
|
||||
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
|
||||
if ld_run_path:
|
||||
LDFLAGS.append('-L%s' % ld_run_path)
|
||||
os.environ['LD_RUN_PATH'] = ld_run_path
|
||||
|
||||
LIBS = [os.popen(PHPPATH + ' --libs').read().rstrip(), '-lphp5']
|
||||
|
||||
GCC_LIST = ['php_plugin']
|
||||
+15
-34
@@ -7,16 +7,16 @@ struct uwsgi_ping {
|
||||
int ping_timeout;
|
||||
} uping;
|
||||
|
||||
struct option uwsgi_ping_options[] = {
|
||||
{"ping", required_argument, 0, LONG_ARGS_PING},
|
||||
{"ping-timeout", required_argument, 0, LONG_ARGS_PING_TIMEOUT},
|
||||
{ 0, 0, 0, 0 }
|
||||
struct uwsgi_option uwsgi_ping_options[] = {
|
||||
{"ping", required_argument, 0, "ping specified uwsgi host", uwsgi_opt_set_str, &uping.ping, UWSGI_OPT_NO_INITIAL | UWSGI_OPT_NO_SERVER},
|
||||
{"ping-timeout", required_argument, 0, "set ping timeout", uwsgi_opt_set_int, &uping.ping_timeout, 0},
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
static void ping() {
|
||||
|
||||
struct wsgi_request ping_req;
|
||||
char *buf = uwsgi_malloc(uwsgi.buffer_size);
|
||||
struct uwsgi_header uh;
|
||||
char *buf = NULL;
|
||||
|
||||
// use a 3 secs timeout by default
|
||||
if (!uping.ping_timeout) uping.ping_timeout = 3;
|
||||
@@ -28,25 +28,22 @@ static void ping() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
memset(&ping_req, 0, sizeof(struct wsgi_request));
|
||||
ping_req.uh.modifier1 = UWSGI_MODIFIER_PING;
|
||||
ping_req.uh.pktsize = 0;
|
||||
ping_req.uh.modifier2 = 0;
|
||||
if (write(fd, &ping_req.uh, 4) != 4) {
|
||||
uh.modifier1 = UWSGI_MODIFIER_PING;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = 0;
|
||||
|
||||
if (write(fd, &uh, 4) != 4) {
|
||||
uwsgi_error("write()");
|
||||
exit(2);
|
||||
}
|
||||
ping_req.poll.fd = fd;
|
||||
ping_req.poll.events = POLLIN;
|
||||
|
||||
ping_req.buffer = buf;
|
||||
|
||||
if (!uwsgi_parse_packet(&ping_req, uping.ping_timeout)) {
|
||||
int ret = uwsgi_read_response(fd, &uh, uping.ping_timeout, &buf);
|
||||
if (ret < 0) {
|
||||
exit(1);
|
||||
}
|
||||
else {
|
||||
if (ping_req.uh.pktsize > 0) {
|
||||
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, ping_req.uh.pktsize, buf);
|
||||
if (uh.pktsize > 0) {
|
||||
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, uh.pktsize, buf);
|
||||
exit(2);
|
||||
}
|
||||
else {
|
||||
@@ -94,27 +91,11 @@ int uwsgi_request_ping(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
int uwsgi_ping_manage_options(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_PING:
|
||||
uwsgi.no_server = 1;
|
||||
uping.ping = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_PING_TIMEOUT:
|
||||
uping.ping_timeout = atoi(optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin ping_plugin = {
|
||||
|
||||
.name = "ping",
|
||||
.modifier1 = 100,
|
||||
.options = uwsgi_ping_options,
|
||||
.manage_opt = uwsgi_ping_manage_options,
|
||||
.request = uwsgi_request_ping,
|
||||
.init = ping_init,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "../../uwsgi.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int connect_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
|
||||
|
||||
// is this a timeout event ?
|
||||
if (interesting_fd == -1) {
|
||||
// am i wating for something ?
|
||||
if (up->fd != -1) {
|
||||
if (up->cycles > (uint64_t) up->timeout) {
|
||||
// reset the cycle
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
// avoid duplicated events
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
// ok register a new event
|
||||
else {
|
||||
if ((up->cycles % up->freq) == 0) {
|
||||
up->fd = uwsgi_connect(up->args, -1, 1);
|
||||
if (up->fd != -1) {
|
||||
// status = CONNECTING
|
||||
up->state = 1;
|
||||
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
|
||||
return 0;
|
||||
}
|
||||
// signal the bad event (if not already bad)
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (up->fd != -1) {
|
||||
// is this event for me ?
|
||||
if (interesting_fd == up->fd) {
|
||||
// uselsess here (we have only one state), only to show a good practice
|
||||
// check the state
|
||||
if (up->state == 1) {
|
||||
if (uwsgi_is_bad_connection(up->fd)) {
|
||||
// signal the bad connection (if needed)
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (!up->bad) {
|
||||
up->bad = 1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// this is a good connection
|
||||
up->cycles = 0;
|
||||
close(up->fd);
|
||||
up->fd = -1;
|
||||
// state = NOOP
|
||||
up->state = 0;
|
||||
if (up->bad) {
|
||||
up->bad = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// default action
|
||||
return 0;
|
||||
}
|
||||
|
||||
int probeconnect_init() {
|
||||
|
||||
uwsgi_probe_register(&uwsgi.probes, "connect", connect_prober_callback);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin probeconnect_plugin = {
|
||||
|
||||
.init = probeconnect_init,
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user