mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -39,3 +39,14 @@ fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
|
||||
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
|
||||
|
||||
@@ -17,3 +17,4 @@ Charles Duffy
|
||||
Lukas Lalinsky
|
||||
Steven Fernandez
|
||||
Łukasz Mierzwa
|
||||
Roy Marples
|
||||
|
||||
@@ -1,3 +1,55 @@
|
||||
*** 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]
|
||||
|
||||
@@ -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));
|
||||
|
||||
+12
-1
@@ -2,7 +2,7 @@
|
||||
|
||||
*** uWSGI/mod_uwsgi ***
|
||||
|
||||
Copyright 2009-2011 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>
|
||||
@@ -346,7 +353,11 @@ 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) ;
|
||||
#endif
|
||||
|
||||
//
|
||||
if (r->user) {
|
||||
|
||||
@@ -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, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal
|
||||
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 =
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = true
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
snmp = 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.cache_max_items) % 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,10 +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));
|
||||
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) {
|
||||
@@ -116,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;
|
||||
|
||||
@@ -132,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;
|
||||
}
|
||||
@@ -159,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;
|
||||
@@ -182,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");
|
||||
@@ -193,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;
|
||||
@@ -267,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;
|
||||
|
||||
@@ -2,7 +2,15 @@
|
||||
|
||||
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;
|
||||
@@ -31,8 +39,8 @@ void cluster_setup() {
|
||||
else if (rlen > 0) {
|
||||
// receive the packet
|
||||
char clusterbuf[4096];
|
||||
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, manage_string_opt, NULL)) {
|
||||
uwsgi_configure();
|
||||
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
|
||||
uwsgi_configure(-1);
|
||||
goto options_parsed;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -314,7 +314,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
break;
|
||||
}
|
||||
free(oe);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("putenv %s\n", ne);
|
||||
#endif
|
||||
|
||||
if (putenv(ne)) {
|
||||
uwsgi_error("putenv()");
|
||||
@@ -334,7 +336,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -350,6 +352,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
colon[0] = 0;
|
||||
}
|
||||
}
|
||||
// initialize to a default value
|
||||
vassal_argv[1] = "--inherit";
|
||||
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
vassal_argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
@@ -366,19 +371,46 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
|
||||
|
||||
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) {
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter+1] = uct->filename;
|
||||
vassal_argv[counter+1] = uct->value;
|
||||
counter+=2;
|
||||
uct = uct->next;
|
||||
}
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// disable stdin
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0)) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
for(i=3;i<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);
|
||||
}
|
||||
@@ -433,6 +465,7 @@ void emperor_loop() {
|
||||
int nevents;
|
||||
int interesting_fd;
|
||||
char notification_message[64];
|
||||
struct rlimit rl;
|
||||
|
||||
uwsgi.emperor_stats_fd = -1;
|
||||
|
||||
@@ -444,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();
|
||||
|
||||
@@ -513,7 +553,11 @@ reconnect:
|
||||
exit(1);
|
||||
}
|
||||
globfree(&g);
|
||||
emperor_absolute_dir = realpath(".", NULL);
|
||||
emperor_absolute_dir = uwsgi_malloc(PATH_MAX+1);
|
||||
if (realpath(".", emperor_absolute_dir) == NULL) {
|
||||
uwsgi_error("realpath()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
ui = &ui_base;
|
||||
@@ -615,10 +659,8 @@ reconnect:
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1) {
|
||||
if (interesting_fd == uwsgi.emperor_stats_fd) {
|
||||
emperor_send_stats(uwsgi.emperor_stats_fd);
|
||||
}
|
||||
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);
|
||||
@@ -627,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) {
|
||||
|
||||
@@ -172,6 +172,7 @@ int event_queue_init() {
|
||||
|
||||
int epfd;
|
||||
|
||||
|
||||
epfd = epoll_create(256);
|
||||
|
||||
if (epfd < 0) {
|
||||
@@ -403,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;
|
||||
@@ -443,7 +445,8 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
uwsgi_error("kevent()");
|
||||
if (errno != EINTR)
|
||||
uwsgi_error("kevent()");
|
||||
}
|
||||
|
||||
if (ret > 0) {
|
||||
|
||||
@@ -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 = uwsgi_fork(name);
|
||||
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 %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 = uwsgi_fork(ug->name);
|
||||
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);
|
||||
}
|
||||
@@ -131,3 +86,71 @@ void gateway_respawn(int id) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
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(10)
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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,217 +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)
|
||||
#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_mutexattr_t) + sizeof(pthread_mutex_t)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutex_t)
|
||||
#else
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
|
||||
#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;
|
||||
}
|
||||
|
||||
void uwsgi_rlock(void *lock) {
|
||||
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
|
||||
uwsgi_lock(lock);
|
||||
return uwsgi_lock_fast_check(uli);
|
||||
#else
|
||||
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
|
||||
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_wlock(void *lock) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock(lock);
|
||||
|
||||
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_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
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_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_rwunlock(void *lock) {
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_unlock(lock);
|
||||
uwsgi_lock_fast(uli);
|
||||
#else
|
||||
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
|
||||
pthread_rwlock_wrlock((pthread_rwlock_t *) uli->lock_ptr);
|
||||
uli->pid = uwsgi.mypid;
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_lock(void *lock) {
|
||||
|
||||
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_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_unlock(void *lock) {
|
||||
|
||||
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_rwlock_init(void *lock) {
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
|
||||
#ifdef OBSOLETE_LINUX_KERNEL
|
||||
uwsgi_lock_init(lock);
|
||||
return uwsgi_lock_fast_init(id);
|
||||
#else
|
||||
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
|
||||
|
||||
pthread_rwlockattr_t attr;
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
|
||||
|
||||
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;
|
||||
@@ -45,10 +136,12 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
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];
|
||||
@@ -58,7 +151,7 @@ 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
|
||||
@@ -67,8 +160,15 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->status == -17) {
|
||||
via = msg3;
|
||||
}
|
||||
else if (wsgi_req->status == -30) {
|
||||
via = msg4;
|
||||
}
|
||||
|
||||
time_request = ctime((const time_t *) &wsgi_req->start_of_request.tv_sec);
|
||||
#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;
|
||||
|
||||
@@ -93,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;
|
||||
@@ -107,35 +204,16 @@ 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(uint64_t *rss, uint64_t *vsz) {
|
||||
void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
|
||||
#ifdef UNBIT
|
||||
*vsz = syscall(356);
|
||||
@@ -146,7 +224,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
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 *) 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);
|
||||
}
|
||||
@@ -157,7 +235,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
|
||||
procfd = open("/proc/self/psinfo", O_RDONLY);
|
||||
if (procfd >= 0) {
|
||||
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
|
||||
if (read(procfd, (char *) &info, sizeof(info)) > 0) {
|
||||
*rss = (uint64_t) info.pr_rssize * 1024;
|
||||
*vsz = (uint64_t) info.pr_size * 1024;
|
||||
}
|
||||
@@ -193,6 +271,13 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
*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;
|
||||
|
||||
@@ -215,12 +300,56 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
|
||||
|
||||
*vsz = 0;
|
||||
*rss = 0;
|
||||
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
|
||||
while (get_next_area_info(0, &cookie, &ai) == B_OK) {
|
||||
*vsz += ai.ram_size;
|
||||
if ( (ai.protection & B_WRITE_AREA) != 0) {
|
||||
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);
|
||||
}
|
||||
@@ -128,8 +131,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);
|
||||
}
|
||||
|
||||
+599
-134
@@ -2,7 +2,332 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void worker_wakeup() {}
|
||||
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() {
|
||||
|
||||
@@ -33,7 +358,7 @@ void master_check_cluster_nodes() {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_fixup_fds(int wid, int muleid) {
|
||||
void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
|
||||
int i;
|
||||
|
||||
@@ -43,48 +368,82 @@ void uwsgi_fixup_fds(int wid, int muleid) {
|
||||
}
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
// 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.shared->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]);
|
||||
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 (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.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]);
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -92,6 +451,10 @@ int uwsgi_respawn_worker(int wid) {
|
||||
int respawns = uwsgi.workers[wid].respawn_count;
|
||||
int i;
|
||||
|
||||
if (uwsgi.threaded_logger) {
|
||||
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
|
||||
|
||||
if (pid == 0) {
|
||||
@@ -108,7 +471,7 @@ int uwsgi_respawn_worker(int wid) {
|
||||
// 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].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;
|
||||
@@ -121,18 +484,18 @@ int uwsgi_respawn_worker(int wid) {
|
||||
// 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);
|
||||
uwsgi_fixup_fds(wid, 0, NULL);
|
||||
|
||||
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
|
||||
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
|
||||
|
||||
if (uwsgi.master_process) {
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
@@ -149,6 +512,11 @@ int uwsgi_respawn_worker(int wid) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.threaded_logger) {
|
||||
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -158,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) {
|
||||
|
||||
@@ -178,20 +545,36 @@ 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;
|
||||
if (ucron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (ucron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
// negative values as interval -1 = * , -5 = */5
|
||||
if (ucron->minute < 0) {
|
||||
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
|
||||
uc_minute = uwsgi_cron_delta->tm_min;
|
||||
}
|
||||
}
|
||||
if (ucron->hour < 0) {
|
||||
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
|
||||
uc_hour = uwsgi_cron_delta->tm_hour;
|
||||
}
|
||||
}
|
||||
if (ucron->month < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
|
||||
uc_month = uwsgi_cron_delta->tm_mon;
|
||||
}
|
||||
}
|
||||
if (ucron->day < 0) {
|
||||
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
}
|
||||
}
|
||||
if (ucron->week < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (ucron->day != -1 && ucron->week != -1) {
|
||||
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;
|
||||
}
|
||||
@@ -205,9 +588,9 @@ void uwsgi_manage_signal_cron(time_t now) {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -227,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) {
|
||||
@@ -236,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;
|
||||
@@ -245,42 +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;
|
||||
if (current_cron->day == -1)
|
||||
uc_day = uwsgi_cron_delta->tm_mday;
|
||||
if (current_cron->week == -1)
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
// 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 < 0) {
|
||||
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
|
||||
uc_week = uwsgi_cron_delta->tm_wday;
|
||||
}
|
||||
}
|
||||
|
||||
int run_task = 0;
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day != -1 && current_cron->week != -1) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
// mday and wday are ORed
|
||||
if (current_cron->day >= 0 && current_cron->week >= 0) {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
|
||||
run_task = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (run_task == 1) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -297,7 +697,7 @@ void uwsgi_manage_command_cron(time_t now) {
|
||||
|
||||
void uwsgi_send_stats(int fd) {
|
||||
|
||||
int i,j;
|
||||
int i, j;
|
||||
struct sockaddr_un client_src;
|
||||
struct uwsgi_app *ua;
|
||||
socklen_t client_src_len = 0;
|
||||
@@ -317,70 +717,105 @@ void uwsgi_send_stats(int fd) {
|
||||
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
|
||||
|
||||
#ifdef __linux__
|
||||
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
|
||||
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()));
|
||||
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, "\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);
|
||||
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\", ");
|
||||
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].suspended) {
|
||||
fprintf(output,"\"status\": \"pause\", ");
|
||||
}
|
||||
else {
|
||||
if (uwsgi.workers[i + 1].sig) {
|
||||
fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
|
||||
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\", ");
|
||||
}
|
||||
}
|
||||
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("\"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);
|
||||
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");
|
||||
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{ ");
|
||||
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( "\"requests\": %llu, ", ua->requests);
|
||||
stats_send_llu( "\"exceptions\": %llu, ", ua->exceptions);
|
||||
|
||||
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);
|
||||
@@ -388,25 +823,55 @@ void uwsgi_send_stats(int fd) {
|
||||
else {
|
||||
fprintf(output, "\"chdir\": \"\" ");
|
||||
}
|
||||
|
||||
if (j == uwsgi.workers[i+1].apps_cnt-1) {
|
||||
fprintf(output,"}\n");
|
||||
|
||||
if (j == uwsgi.workers[i + 1].apps_cnt - 1) {
|
||||
fprintf(output, "}\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"},\n");
|
||||
fprintf(output, "},\n");
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(output,"\t\t]");
|
||||
fprintf(output, "\t\t]");
|
||||
|
||||
if (i == uwsgi.numproc-1) {
|
||||
fprintf(output,"}\n");
|
||||
if (i == uwsgi.numproc - 1) {
|
||||
fprintf(output, "}\n");
|
||||
}
|
||||
else {
|
||||
fprintf(output,"},\n");
|
||||
fprintf(output, "},\n");
|
||||
}
|
||||
}
|
||||
|
||||
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>
|
||||
|
||||
@@ -41,20 +41,20 @@ void uwsgi_mule(int id) {
|
||||
uwsgi.mules[id-1].id = id;
|
||||
uwsgi.mules[id-1].pid = getpid();
|
||||
|
||||
uwsgi_fixup_fds(0, id);
|
||||
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 < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->master_fixup) {
|
||||
uwsgi.p[i]->master_fixup(1);
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->post_fork) {
|
||||
uwsgi.p[i]->post_fork();
|
||||
}
|
||||
@@ -62,7 +62,7 @@ void uwsgi_mule(int id) {
|
||||
|
||||
|
||||
if (uwsgi.mules[id-1].patch) {
|
||||
for (i = 0; i < 0xFF; i++) {
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->mule) {
|
||||
if (uwsgi.p[i]->mule(uwsgi.mules[id-1].patch) == 1) {
|
||||
// never here
|
||||
@@ -184,7 +184,7 @@ void uwsgi_mule_handler() {
|
||||
}
|
||||
else {
|
||||
int i,found = 0;
|
||||
for(i=0;i<0xff;i++) {
|
||||
for(i=0;i<256;i++) {
|
||||
if (uwsgi.p[i]->mule_msg) {
|
||||
if (uwsgi.p[i]->mule_msg(message, len)) {
|
||||
found = 1;
|
||||
@@ -356,3 +356,24 @@ clear:
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
@@ -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
+1
-1
@@ -63,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:
|
||||
|
||||
+68
-41
@@ -2,54 +2,25 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#define CARBON_OPT_BASE 178000
|
||||
#define CARBON_OPT_CARBON CARBON_OPT_BASE+1
|
||||
#define CARBON_OPT_CARBON_ID CARBON_OPT_BASE+2
|
||||
#define CARBON_OPT_CARBON_FREQ CARBON_OPT_BASE+3
|
||||
#define CARBON_OPT_CARBON_TIMEOUT CARBON_OPT_BASE+4
|
||||
|
||||
struct uwsgi_carbon {
|
||||
struct uwsgi_string_list *servers;
|
||||
int freq;
|
||||
int timeout;
|
||||
char *id;
|
||||
int no_workers;
|
||||
} u_carbon;
|
||||
|
||||
struct option carbon_options[] = {
|
||||
{"carbon", required_argument, 0, CARBON_OPT_CARBON},
|
||||
{"carbon-timeout", required_argument, 0, CARBON_OPT_CARBON_TIMEOUT},
|
||||
{"carbon-freq", required_argument, 0, CARBON_OPT_CARBON_FREQ},
|
||||
{"carbon-id", required_argument, 0, CARBON_OPT_CARBON_ID},
|
||||
{0, 0, 0, 0},
|
||||
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},
|
||||
|
||||
};
|
||||
|
||||
|
||||
int carbon_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int carbon_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case CARBON_OPT_CARBON:
|
||||
uwsgi.master_process = 1;
|
||||
uwsgi_string_new_list(&u_carbon.servers, optarg);
|
||||
return 1;
|
||||
case CARBON_OPT_CARBON_ID:
|
||||
u_carbon.id = optarg;
|
||||
return 1;
|
||||
case CARBON_OPT_CARBON_FREQ:
|
||||
u_carbon.freq = atoi(optarg);
|
||||
return 1;
|
||||
case CARBON_OPT_CARBON_TIMEOUT:
|
||||
u_carbon.timeout = atoi(optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void carbon_post_init() {
|
||||
|
||||
int i;
|
||||
@@ -94,30 +65,86 @@ void carbon_master_cycle() {
|
||||
// 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,
|
||||
.manage_opt = carbon_opt,
|
||||
|
||||
.master_cycle = carbon_master_cycle,
|
||||
|
||||
.post_init = carbon_post_init,
|
||||
.init = carbon_init,
|
||||
};
|
||||
|
||||
+861
-61
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']
|
||||
+7
-24
@@ -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},
|
||||
};
|
||||
|
||||
|
||||
@@ -244,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;
|
||||
@@ -363,8 +363,7 @@ 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) {
|
||||
|
||||
@@ -423,7 +422,7 @@ 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("uWSGI erlang c-node", erlang_loop) == NULL) {
|
||||
if (register_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
|
||||
uwsgi_log("unable to register the erlang gateway\n");
|
||||
exit(1);
|
||||
}
|
||||
@@ -433,26 +432,10 @@ int erlang_init() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int erlang_opt(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_ERLANG:
|
||||
uwsgi.master_process = 1;
|
||||
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,10 +1,5 @@
|
||||
#include <ei.h>
|
||||
|
||||
#define LONG_ARGS_ERLANG 17012
|
||||
#define LONG_ARGS_ERLANG_COOKIE 17013
|
||||
|
||||
|
||||
|
||||
struct uwsgi_erlang_process {
|
||||
|
||||
char name[0xff];
|
||||
|
||||
@@ -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']
|
||||
|
||||
+575
-696
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':
|
||||
|
||||
+14
-18
@@ -3,17 +3,13 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
struct option gevent_options[] = {
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
#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] = uwsgi.wsgi_req
|
||||
#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);\
|
||||
if (ret) { Py_DECREF(ret); }\
|
||||
ret = PyObject_CallMethod(watcher, "stop", NULL);\
|
||||
if (ret) Py_DECREF(ret);
|
||||
if (ret) { Py_DECREF(ret); }
|
||||
|
||||
struct uwsgi_gevent {
|
||||
PyObject *greenlet_switch;
|
||||
@@ -28,6 +24,14 @@ struct uwsgi_gevent {
|
||||
} 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) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
@@ -94,7 +98,6 @@ PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
|
||||
uwsgi_log("async queue is full !!!\n");
|
||||
goto clear;
|
||||
}
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
// fill wsgi_request structure
|
||||
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi.sockets );
|
||||
@@ -111,7 +114,6 @@ PyObject *py_uwsgi_gevent_main(PyObject * self, PyObject * args) {
|
||||
|
||||
// accept the connection
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi.sockets->fd)) {
|
||||
uwsgi_close_request(wsgi_req);
|
||||
free_req_queue;
|
||||
goto clear;
|
||||
}
|
||||
@@ -154,10 +156,10 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
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");
|
||||
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
// create a watcher for request socket
|
||||
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 1);
|
||||
if (!watcher) goto clear1;
|
||||
@@ -171,9 +173,6 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
PyObject *ret = uwsgi_gevent_wait(watcher, timer, greenlet_switch);
|
||||
if (!ret) goto clear_and_stop;
|
||||
|
||||
// do not forget to overwrite this pointer each time !!!
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
// we can safely decref here as watcher and timer has got a +1 for start() method
|
||||
Py_DECREF(ret);
|
||||
if (ret == timer) {
|
||||
@@ -200,7 +199,6 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
wsgi_req->async_status = uwsgi.p[wsgi_req->uh.modifier1]->request(wsgi_req);
|
||||
if (wsgi_req->async_status <= UWSGI_OK) {
|
||||
goto clear;
|
||||
@@ -224,8 +222,6 @@ clear1:
|
||||
Py_DECREF(current_greenlet);
|
||||
uwsgi_close_request(wsgi_req);
|
||||
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
|
||||
free_req_queue;
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -250,6 +246,7 @@ void gevent_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi.current_wsgi_req = uwsgi_gevent_current_wsgi_req;
|
||||
|
||||
PyObject *gevent_dict = get_uwsgi_pydict("gevent");
|
||||
if (!gevent_dict) uwsgi_pyexit;
|
||||
@@ -352,5 +349,4 @@ struct uwsgi_plugin gevent_plugin = {
|
||||
|
||||
.name = "gevent",
|
||||
.init = gevent_init,
|
||||
.options = gevent_options,
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+600
-546
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;
|
||||
@@ -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,
|
||||
|
||||
+7
-19
@@ -3,12 +3,10 @@
|
||||
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},
|
||||
|
||||
};
|
||||
|
||||
@@ -30,7 +28,10 @@ int nagios() {
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -70,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']
|
||||
@@ -7,10 +7,10 @@ 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() {
|
||||
@@ -91,28 +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_initial_output = 1;
|
||||
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,
|
||||
};
|
||||
|
||||
+23
-15
@@ -11,27 +11,33 @@
|
||||
|
||||
struct uwsgi_perl {
|
||||
|
||||
int fd;
|
||||
char *psgibuffer;
|
||||
// path of the statically loaded main app
|
||||
char *psgi;
|
||||
// locallib path
|
||||
char *locallib;
|
||||
|
||||
// perl argv for initialization
|
||||
char *embedding[3];
|
||||
PerlInterpreter *main;
|
||||
pthread_key_t u_interpreter;
|
||||
PerlInterpreter **interp;
|
||||
SV *psgi_main;
|
||||
SV **psgi_func;
|
||||
CV *stream_responder;
|
||||
HV *streaming_stash;
|
||||
HV *input_stash;
|
||||
HV *error_stash;
|
||||
|
||||
// check for Devel::StackTrace
|
||||
int no_die_catch;
|
||||
int stacktrace_available;
|
||||
|
||||
// this is a pointer to the main list of interpreters (required for signals, rpc....);
|
||||
PerlInterpreter **main;
|
||||
|
||||
// a lock for dynamic apps
|
||||
pthread_mutex_t lock_loader;
|
||||
|
||||
// this fields must be heavy protected in threaded modes
|
||||
int tmp_current_i;
|
||||
HV **tmp_streaming_stash;
|
||||
HV **tmp_input_stash;
|
||||
HV **tmp_error_stash;
|
||||
|
||||
CV **tmp_stream_responder;
|
||||
};
|
||||
|
||||
#define LONG_ARGS_PERL_BASE 17000 + ((5 + 1) * 1000)
|
||||
#define LONG_ARGS_PSGI LONG_ARGS_PERL_BASE + 1
|
||||
#define LONG_ARGS_PERL_LOCAL_LIB LONG_ARGS_PERL_BASE + 2
|
||||
|
||||
void init_perl_embedded_module(void);
|
||||
void uwsgi_psgi_app(void);
|
||||
int psgi_response(struct wsgi_request *, AV*);
|
||||
@@ -41,3 +47,5 @@ int psgi_response(struct wsgi_request *, AV*);
|
||||
|
||||
SV *uwsgi_perl_obj_call(SV *, char *);
|
||||
int uwsgi_perl_obj_can(SV *, char *, size_t);
|
||||
int init_psgi_app(struct wsgi_request *, char *, uint16_t, PerlInterpreter **);
|
||||
PerlInterpreter *uwsgi_perl_new_interpreter(void);
|
||||
|
||||
+249
-84
@@ -15,19 +15,23 @@ XS(XS_input_seek) {
|
||||
|
||||
XS(XS_error) {
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
psgi_check_args(0);
|
||||
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.error_stash);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[wsgi_req->async_id]);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_input) {
|
||||
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
psgi_check_args(0);
|
||||
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.input_stash);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[wsgi_req->async_id]);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
@@ -35,6 +39,7 @@ XS(XS_stream)
|
||||
{
|
||||
dXSARGS;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
@@ -47,7 +52,7 @@ XS(XS_stream)
|
||||
while (psgi_response(wsgi_req, response) != UWSGI_OK);
|
||||
|
||||
SvREFCNT_dec(response);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.streaming_stash);
|
||||
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[wsgi_req->async_id]);
|
||||
XSRETURN(1);
|
||||
}
|
||||
else {
|
||||
@@ -87,7 +92,7 @@ XS(XS_input_read) {
|
||||
}
|
||||
else if (uwsgi.post_buffering > 0) {
|
||||
fd = -1;
|
||||
if (wsgi_req->post_cl <= (size_t) uwsgi.post_buffering) {
|
||||
if (wsgi_req->post_cl > (size_t) uwsgi.post_buffering) {
|
||||
fd = fileno((FILE *)wsgi_req->async_post);
|
||||
}
|
||||
}
|
||||
@@ -184,6 +189,21 @@ XS(XS_error_print) {
|
||||
XSRETURN(0);
|
||||
}
|
||||
|
||||
XS(XS_uwsgi_stacktrace) {
|
||||
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(0);
|
||||
|
||||
uwsgi_log("*** uWSGI perl stacktrace ***\n");
|
||||
SV *ret = perl_eval_pv("Devel::StackTrace->new->as_string;", 0);
|
||||
uwsgi_log("%s", SvPV_nolen(ret));
|
||||
uwsgi_log("*** end of perl stacktrace ***\n\n");
|
||||
XSRETURN(0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* automatically generated */
|
||||
|
||||
EXTERN_C void xs_init (pTHX);
|
||||
@@ -203,18 +223,21 @@ xs_init(pTHX)
|
||||
newXS("uwsgi::input::read", XS_input_read, "uwsgi::input");
|
||||
newXS("uwsgi::input::seek", XS_input_seek, "uwsgi::input");
|
||||
|
||||
uperl.input_stash = gv_stashpv("uwsgi::input", 0);
|
||||
uperl.tmp_input_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::input", 0);
|
||||
|
||||
newXS("uwsgi::error::new", XS_error, "uwsgi::error");
|
||||
newXS("uwsgi::error::print", XS_error_print, "uwsgi::print");
|
||||
uperl.error_stash = gv_stashpv("uwsgi::error", 0);
|
||||
uperl.tmp_error_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::error", 0);
|
||||
|
||||
uperl.stream_responder = newXS("uwsgi::stream", XS_stream, "uwsgi");
|
||||
uperl.tmp_stream_responder[uperl.tmp_current_i] = newXS("uwsgi::stream", XS_stream, "uwsgi");
|
||||
|
||||
newXS("uwsgi::streaming::write", XS_streaming_write, "uwsgi::streaming");
|
||||
newXS("uwsgi::streaming::close", XS_streaming_close, "uwsgi::streaming");
|
||||
|
||||
uperl.streaming_stash = gv_stashpv("uwsgi::streaming", 0);
|
||||
newXS("uwsgi::stacktrace", XS_uwsgi_stacktrace, "uwsgi");
|
||||
|
||||
|
||||
uperl.tmp_streaming_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::streaming", 0);
|
||||
|
||||
#ifdef UWSGI_EMBEDDED
|
||||
init_perl_embedded_module();
|
||||
@@ -224,87 +247,229 @@ xs_init(pTHX)
|
||||
|
||||
/* end of automagically generated part */
|
||||
|
||||
PerlInterpreter *uwsgi_perl_new_interpreter(void) {
|
||||
|
||||
PerlInterpreter *pi = perl_alloc();
|
||||
if (!pi) {
|
||||
uwsgi_log("unable to allocate perl interpreter\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
PERL_SET_CONTEXT(pi);
|
||||
|
||||
PL_perl_destruct_level = 2;
|
||||
PL_origalen = 1;
|
||||
perl_construct(pi);
|
||||
// over-engeneering
|
||||
PL_origalen = 1;
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
static void uwsgi_perl_free_stashes(void) {
|
||||
free(uperl.tmp_streaming_stash);
|
||||
free(uperl.tmp_input_stash);
|
||||
free(uperl.tmp_error_stash);
|
||||
free(uperl.tmp_stream_responder);
|
||||
}
|
||||
|
||||
int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, PerlInterpreter **interpreters) {
|
||||
|
||||
struct stat st;
|
||||
int i;
|
||||
SV **callables;
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
|
||||
char *app_name = uwsgi_concat2n(app, app_len, "", 0);
|
||||
|
||||
// prepare for $0
|
||||
uperl.embedding[1] = app_name;
|
||||
|
||||
int fd = open(app_name, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(app_name);
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st)) {
|
||||
uwsgi_error("fstat()");
|
||||
close(fd);
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
char *buf = uwsgi_calloc(st.st_size+1);
|
||||
if (read(fd, buf, st.st_size) != st.st_size) {
|
||||
uwsgi_error("read()");
|
||||
close(fd);
|
||||
free(buf);
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
// the first (default) app, should always be loaded in the main interpreter
|
||||
if (interpreters == NULL) {
|
||||
if (uwsgi_apps_cnt) {
|
||||
interpreters = uwsgi_calloc(sizeof(PerlInterpreter *) * uwsgi.threads);
|
||||
interpreters[0] = uwsgi_perl_new_interpreter();
|
||||
if (!interpreters[0]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
free(interpreters);
|
||||
goto clear2;
|
||||
}
|
||||
}
|
||||
else {
|
||||
interpreters = uperl.main;
|
||||
}
|
||||
}
|
||||
|
||||
if (!interpreters) {
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
|
||||
callables = uwsgi_calloc(sizeof(SV *) * uwsgi.threads);
|
||||
uperl.tmp_streaming_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
|
||||
uperl.tmp_input_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
|
||||
uperl.tmp_error_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
|
||||
uperl.tmp_stream_responder = uwsgi_calloc(sizeof(CV *) * uwsgi.threads);
|
||||
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
|
||||
if (i > 0 && interpreters != uperl.main) {
|
||||
|
||||
interpreters[i] = uwsgi_perl_new_interpreter();
|
||||
if (!interpreters[i]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
// what to do here ? i hope no-one will use threads with dynamic apps...but clear the whole stuff...
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
while(i>=0) {
|
||||
perl_destruct(interpreters[i]);
|
||||
perl_free(interpreters[i]);
|
||||
goto clear2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PERL_SET_CONTEXT(interpreters[i]);
|
||||
|
||||
uperl.tmp_current_i = i;
|
||||
|
||||
|
||||
if (uperl.locallib) {
|
||||
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
|
||||
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
|
||||
uperl.embedding[2] = app_name;
|
||||
if (perl_parse(interpreters[i], xs_init, 3, uperl.embedding, NULL)) {
|
||||
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
|
||||
free(uperl.embedding[1]);
|
||||
uperl.embedding[1] = app_name;
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
goto clear;
|
||||
}
|
||||
free(uperl.embedding[1]);
|
||||
uperl.embedding[1] = app_name;
|
||||
}
|
||||
else {
|
||||
if (perl_parse(interpreters[i], xs_init, 2, uperl.embedding, NULL)) {
|
||||
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
perl_eval_pv("use IO::Handle;", 0);
|
||||
perl_eval_pv("use IO::File;", 0);
|
||||
if (!uperl.no_die_catch) {
|
||||
perl_eval_pv("use Devel::StackTrace;", 0);
|
||||
if (!SvTRUE(ERRSV)) {
|
||||
uperl.stacktrace_available = 1;
|
||||
perl_eval_pv("$SIG{__DIE__} = \\&uwsgi::stacktrace;", 0);
|
||||
}
|
||||
}
|
||||
|
||||
SV *dollar_zero = get_sv("0", GV_ADD);
|
||||
sv_setsv(dollar_zero, newSVpv(app, app_len));
|
||||
|
||||
callables[i] = perl_eval_pv(uwsgi_concat4("#line 1 ", app_name, "\n", buf), 0);
|
||||
if (!callables[i]) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
// what to do here ? i hope no-one will use threads with dynamic apps...
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
goto clear;
|
||||
}
|
||||
|
||||
PERL_SET_CONTEXT(interpreters[0]);
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
free(callables);
|
||||
uwsgi_perl_free_stashes();
|
||||
goto clear;
|
||||
}
|
||||
|
||||
int id = uwsgi_apps_cnt;
|
||||
struct uwsgi_app *wi = NULL;
|
||||
|
||||
if (wsgi_req) {
|
||||
// we need a copy of app_id
|
||||
wi = uwsgi_add_app(id, 5, uwsgi_concat2n(wsgi_req->appid, wsgi_req->appid_len, "", 0), wsgi_req->appid_len, interpreters, callables);
|
||||
}
|
||||
else {
|
||||
wi = uwsgi_add_app(id, 5, "", 0, interpreters, callables);
|
||||
}
|
||||
|
||||
wi->started_at = now;
|
||||
wi->startup_time = uwsgi_now() - now;
|
||||
|
||||
uwsgi_log("PSGI app %d (%s) loaded in %d seconds at %p (interpreter %p)\n", id, app_name, (int) wi->startup_time, callables[0], interpreters[0]);
|
||||
free(app_name);
|
||||
|
||||
// copy global data to app-specific areas
|
||||
wi->stream = uperl.tmp_streaming_stash;
|
||||
wi->input = uperl.tmp_input_stash;
|
||||
wi->error = uperl.tmp_error_stash;
|
||||
wi->responder0 = uperl.tmp_stream_responder;
|
||||
|
||||
uwsgi_emulate_cow_for_apps(id);
|
||||
|
||||
|
||||
// restore context if required
|
||||
if (interpreters != uperl.main) {
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
}
|
||||
|
||||
return id;
|
||||
|
||||
clear:
|
||||
if (interpreters != uperl.main) {
|
||||
for(i=0;i<uwsgi.threads;i++) {
|
||||
perl_destruct(interpreters[i]);
|
||||
perl_free(interpreters[i]);
|
||||
}
|
||||
free(interpreters);
|
||||
}
|
||||
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
clear2:
|
||||
free(app_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_psgi_app() {
|
||||
|
||||
struct stat stat_psgi;
|
||||
int id = uwsgi_apps_cnt;
|
||||
|
||||
if (uperl.psgi) {
|
||||
|
||||
// two-pass loading: parse the script -> eval the script
|
||||
|
||||
|
||||
|
||||
if (uperl.locallib) {
|
||||
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
|
||||
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
|
||||
uperl.embedding[2] = uperl.psgi;
|
||||
if (perl_parse(uperl.main, xs_init, 3, uperl.embedding, NULL)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uperl.embedding[1] = uperl.psgi;
|
||||
if (perl_parse(uperl.main, xs_init, 2, uperl.embedding, NULL)) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
perl_eval_pv("use IO::Handle;", 0);
|
||||
perl_eval_pv("use IO::File;", 0);
|
||||
|
||||
SV *dollar_zero = get_sv("0", GV_ADD);
|
||||
sv_setsv(dollar_zero, newSVpv(uperl.psgi, 0));
|
||||
|
||||
SV *dollar_slash = get_sv("/", GV_ADD);
|
||||
sv_setsv(dollar_slash, newRV_inc(newSViv(uwsgi.buffer_size)));
|
||||
|
||||
uperl.fd = open(uperl.psgi, O_RDONLY);
|
||||
if (uperl.fd < 0) {
|
||||
uwsgi_error_open(uperl.psgi);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (fstat(uperl.fd, &stat_psgi)) {
|
||||
uwsgi_error("fstat()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uperl.psgibuffer = malloc(stat_psgi.st_size + 1);
|
||||
if (!uperl.psgibuffer) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (read(uperl.fd, uperl.psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
|
||||
uwsgi_error("read()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uperl.psgibuffer[stat_psgi.st_size] = 0;
|
||||
|
||||
uperl.psgi_main = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
|
||||
if (!uperl.psgi_main) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.threads < 2) {
|
||||
free(uperl.psgibuffer);
|
||||
close(uperl.fd);
|
||||
}
|
||||
|
||||
uwsgi_add_app(id, 5, "", 0);
|
||||
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
|
||||
|
||||
//load app in the main interpreter list
|
||||
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
+133
-114
@@ -9,11 +9,12 @@ extern struct uwsgi_perl uperl;
|
||||
struct uwsgi_perl uperl;
|
||||
#endif
|
||||
|
||||
struct option uwsgi_perl_options[] = {
|
||||
struct uwsgi_option uwsgi_perl_options[] = {
|
||||
|
||||
{"psgi", required_argument, 0, LONG_ARGS_PSGI},
|
||||
{"perl-local-lib", required_argument, 0, LONG_ARGS_PERL_LOCAL_LIB},
|
||||
{0, 0, 0, 0},
|
||||
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
|
||||
{"perl-no-die-catch", no_argument, 0, "do not catch $SIG{__DIE__}", uwsgi_opt_true, &uperl.no_die_catch, 0},
|
||||
{"perl-local-lib", required_argument, 0, "set perl locallib path", uwsgi_opt_set_str, &uperl.locallib, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
@@ -22,8 +23,7 @@ extern struct http_status_codes hsc[];
|
||||
SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
|
||||
SV *newobj;
|
||||
// set current context ?
|
||||
dTHX;
|
||||
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -48,21 +48,21 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
SV *uwsgi_perl_call_stream(SV *func) {
|
||||
|
||||
SV *ret = NULL;
|
||||
// set current context ?
|
||||
dTHX;
|
||||
dSP;
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs( sv_2mortal(newRV((SV*) uperl.stream_responder)));
|
||||
XPUSHs( sv_2mortal(newRV((SV*) ((SV **)wi->responder0)[wsgi_req->async_id])));
|
||||
PUTBACK;
|
||||
|
||||
call_sv( func, G_SCALAR | G_EVAL);
|
||||
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
ret = SvREFCNT_inc(POPs);
|
||||
@@ -78,8 +78,7 @@ SV *uwsgi_perl_call_stream(SV *func) {
|
||||
int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
|
||||
|
||||
int ret;
|
||||
// set current context ? needed for threading
|
||||
dTHX;
|
||||
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -102,12 +101,10 @@ int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
SV *uwsgi_perl_obj_call(SV *obj, char *method) {
|
||||
|
||||
SV *ret = NULL;
|
||||
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -141,7 +138,6 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
|
||||
|
||||
AV *ret = NULL;
|
||||
|
||||
dTHX;
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
@@ -156,7 +152,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
internal_server_error(wsgi_req, "exception raised");
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
ret = (AV *) SvREFCNT_inc(SvRV(POPs));
|
||||
@@ -284,10 +280,19 @@ int uwsgi_perl_init(){
|
||||
struct http_status_codes *http_sc;
|
||||
|
||||
int argc;
|
||||
int i;
|
||||
|
||||
uperl.embedding[0] = "";
|
||||
uperl.embedding[1] = "-e";
|
||||
uperl.embedding[2] = "0";
|
||||
|
||||
#ifndef USE_ITHREADS
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi_log("your Perl environment does not support threads\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (setenv("PLACK_ENV", "uwsgi", 0)) {
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
@@ -296,92 +301,102 @@ int uwsgi_perl_init(){
|
||||
uwsgi_error("setenv()");
|
||||
}
|
||||
|
||||
#ifdef PERL_VERSION_STRING
|
||||
uwsgi_log("initializing Perl %s environment\n", PERL_VERSION_STRING);
|
||||
#else
|
||||
uwsgi_log("initializing Perl environment\n");
|
||||
#endif
|
||||
|
||||
argc = 3;
|
||||
|
||||
PERL_SYS_INIT3(&argc, (char ***) &uperl.embedding, &environ);
|
||||
uperl.main = perl_alloc();
|
||||
if (!uperl.main) {
|
||||
uwsgi_log("unable to allocate perl interpreter\n");
|
||||
|
||||
uperl.main = uwsgi_calloc(sizeof(PerlInterpreter *) * uwsgi.threads);
|
||||
|
||||
uperl.main[0] = uwsgi_perl_new_interpreter();
|
||||
if (!uperl.main[0]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
dTHXa(uperl.main);
|
||||
PERL_SET_CONTEXT(uperl.main);
|
||||
for(i=1;i<uwsgi.threads;i++) {
|
||||
uperl.main[i] = uwsgi_perl_new_interpreter();
|
||||
if (!uperl.main[i]) {
|
||||
uwsgi_log("unable to create new perl interpreter for thread %d\n", i+1);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
PL_perl_destruct_level = 2;
|
||||
PL_origalen = 1;
|
||||
perl_construct(uperl.main);
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
|
||||
// filling http status codes
|
||||
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
|
||||
http_sc->message_size = strlen(http_sc->message);
|
||||
}
|
||||
|
||||
PL_origalen = 1;
|
||||
#ifdef PERL_VERSION_STRING
|
||||
uwsgi_log("initialized Perl %s main interpreter at %p\n", PERL_VERSION_STRING, uperl.main[0]);
|
||||
#else
|
||||
uwsgi_log("initialized Perl main interpreter at %p\n", uperl.main[0]);
|
||||
#endif
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_ITHREADS
|
||||
void uwsgi_perl_enable_threads() {
|
||||
|
||||
if (pthread_key_create(&uperl.u_interpreter, NULL)) {
|
||||
uwsgi_error("pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uperl.interp = uwsgi_malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
|
||||
uperl.interp[0] = uperl.main;
|
||||
|
||||
uperl.psgi_func = uwsgi_malloc( sizeof(SV*) * uwsgi.threads );
|
||||
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
SV **harakiri;
|
||||
SV *psgi_func = uperl.psgi_main;
|
||||
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (wsgi_req->async_status == UWSGI_AGAIN) {
|
||||
return psgi_response(wsgi_req, wsgi_req->async_placeholder);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Standard PSGI request */
|
||||
if (!wsgi_req->uh.pktsize) {
|
||||
uwsgi_log("Invalid PSGI request. skip.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
psgi_func = uperl.psgi_func[wsgi_req->async_id];
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 5);
|
||||
// if it is -1, try to load a dynamic app
|
||||
if (wsgi_req->app_id == -1) {
|
||||
if (wsgi_req->dynamic) {
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_lock(&uperl.lock_loader);
|
||||
}
|
||||
|
||||
if (wsgi_req->script_len > 0) {
|
||||
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->script, wsgi_req->script_len, NULL);
|
||||
}
|
||||
else if (wsgi_req->file_len > 0) {
|
||||
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->file, wsgi_req->file_len, NULL);
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_unlock(&uperl.lock_loader);
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
internal_server_error(wsgi_req, "Perl application not found");
|
||||
// nothing to clear/free
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
|
||||
wi->requests++;
|
||||
|
||||
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
|
||||
PERL_SET_CONTEXT(((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id]);
|
||||
}
|
||||
|
||||
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
|
||||
wsgi_req->async_environ = build_psgi_env(wsgi_req);
|
||||
if (!wsgi_req->async_environ) goto clear;
|
||||
|
||||
wsgi_req->async_result = psgi_call(wsgi_req, psgi_func, wsgi_req->async_environ);
|
||||
wsgi_req->async_result = psgi_call(wsgi_req, ((SV **)wi->callable)[wsgi_req->async_id], wsgi_req->async_environ);
|
||||
if (!wsgi_req->async_result) goto clear;
|
||||
|
||||
if (SvTYPE((AV *)wsgi_req->async_result) == SVt_PVCV) {
|
||||
@@ -419,6 +434,11 @@ clear:
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
// restore main interpreter if needed
|
||||
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
|
||||
PERL_SET_CONTEXT(uperl.main[wsgi_req->async_id]);
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -435,56 +455,6 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_ITHREADS
|
||||
void uwsgi_perl_init_thread(int core_id) {
|
||||
|
||||
|
||||
|
||||
if (core_id > 0) {
|
||||
uperl.interp[core_id] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
|
||||
if (!uperl.interp[core_id]) {
|
||||
uwsgi_log("unable to create new perl interpreter\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
dTHXa(uperl.interp[core_id]);
|
||||
PERL_SET_CONTEXT(uperl.interp[core_id]);
|
||||
|
||||
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
|
||||
|
||||
uperl.psgi_func[0] = uperl.psgi_main;
|
||||
if (core_id > 0) {
|
||||
uperl.psgi_func[core_id] = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
|
||||
|
||||
if (!uperl.psgi_func[core_id]) {
|
||||
uwsgi_log("unable to find PSGI function entry point.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
int uwsgi_perl_manage_options(int i, char *optarg) {
|
||||
|
||||
switch(i) {
|
||||
case LONG_ARGS_PSGI:
|
||||
uperl.psgi = optarg;
|
||||
return 1;
|
||||
case LONG_ARGS_PERL_LOCAL_LIB:
|
||||
uperl.locallib = optarg;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_perl_magic(char *mountpoint, char *lazy) {
|
||||
|
||||
if (!strcmp(lazy+strlen(lazy)-5, ".psgi")) {
|
||||
@@ -500,6 +470,55 @@ int uwsgi_perl_magic(char *mountpoint, char *lazy) {
|
||||
|
||||
}
|
||||
|
||||
// taken from Torsten Foertsch AfterFork.xs
|
||||
void uwsgi_perl_post_fork() {
|
||||
|
||||
GV *tmpgv = gv_fetchpv("$", TRUE, SVt_PV);
|
||||
if (tmpgv) {
|
||||
SvREADONLY_off(GvSV(tmpgv));
|
||||
sv_setiv(GvSV(tmpgv), (IV)getpid());
|
||||
SvREADONLY_on(GvSV(tmpgv));
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_perl_mount_app(char *mountpoint, char *app, int regexp) {
|
||||
|
||||
if (uwsgi_endswith(app, ".pl") || uwsgi_endswith(app, ".psgi")) {
|
||||
uwsgi.wsgi_req->appid = mountpoint;
|
||||
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
|
||||
|
||||
return init_psgi_app(uwsgi.wsgi_req, app, strlen(app), NULL);
|
||||
}
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_perl_init_thread(int core_id) {
|
||||
|
||||
#ifdef USE_ITHREADS
|
||||
PERL_SET_CONTEXT(uperl.main[core_id]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_perl_pthread_prepare(void) {
|
||||
pthread_mutex_lock(&uperl.lock_loader);
|
||||
}
|
||||
|
||||
void uwsgi_perl_pthread_parent(void) {
|
||||
pthread_mutex_unlock(&uperl.lock_loader);
|
||||
}
|
||||
|
||||
void uwsgi_perl_pthread_child(void) {
|
||||
pthread_mutex_init(&uperl.lock_loader, NULL);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_perl_enable_threads(void) {
|
||||
#ifdef USE_ITHREADS
|
||||
pthread_mutex_init(&uperl.lock_loader, NULL);
|
||||
pthread_atfork(uwsgi_perl_pthread_prepare, uwsgi_perl_pthread_parent, uwsgi_perl_pthread_child);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct uwsgi_plugin psgi_plugin = {
|
||||
|
||||
@@ -507,16 +526,16 @@ struct uwsgi_plugin psgi_plugin = {
|
||||
.modifier1 = 5,
|
||||
.init = uwsgi_perl_init,
|
||||
.options = uwsgi_perl_options,
|
||||
|
||||
.init_apps = uwsgi_psgi_app,
|
||||
//.magic = uwsgi_perl_magic,
|
||||
//.help = uwsgi_perl_help,
|
||||
#ifdef USE_ITHREADS
|
||||
.enable_threads = uwsgi_perl_enable_threads,
|
||||
.mount_app = uwsgi_perl_mount_app,
|
||||
|
||||
.init_thread = uwsgi_perl_init_thread,
|
||||
#endif
|
||||
.manage_opt = uwsgi_perl_manage_options,
|
||||
|
||||
.post_fork = uwsgi_perl_post_fork,
|
||||
.request = uwsgi_perl_request,
|
||||
.after_request = uwsgi_perl_after_request,
|
||||
.enable_threads = uwsgi_perl_enable_threads,
|
||||
|
||||
.magic = uwsgi_perl_magic,
|
||||
};
|
||||
|
||||
@@ -126,9 +126,7 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
vi = (i*2)+base;
|
||||
wsgi_req->hvec[vi].iov_base = "\r\n"; wsgi_req->hvec[vi].iov_len = 2;
|
||||
|
||||
if ( !(wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, vi+1)) ) {
|
||||
uwsgi_error("writev()");
|
||||
}
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, vi+1);
|
||||
|
||||
hitem = av_fetch(response, 2, 0);
|
||||
|
||||
|
||||
@@ -76,13 +76,21 @@ XS(XS_wait_fd_write) {
|
||||
|
||||
#endif
|
||||
|
||||
XS(XS_signal) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
uwsgi_signal_send(uwsgi.signal_socket, SvIV(ST(0)));
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_reload) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(0);
|
||||
psgi_check_args(0);
|
||||
|
||||
uwsgi_log("SENDING HUP TO %d\n", (int) uwsgi.workers[0].pid);
|
||||
if (kill(uwsgi.workers[0].pid, SIGHUP)) {
|
||||
uwsgi_error("kill()");
|
||||
XSRETURN_NO;
|
||||
@@ -96,14 +104,19 @@ XS(XS_cache_set) {
|
||||
char *key, *val;
|
||||
STRLEN keylen;
|
||||
STRLEN vallen;
|
||||
|
||||
if (uwsgi.cache_max_items == 0) goto clear;
|
||||
|
||||
psgi_check_args(2);
|
||||
|
||||
key = SvPV(ST(0), keylen);
|
||||
val = SvPV(ST(1), vallen);
|
||||
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
uwsgi_cache_set(key, (uint16_t) keylen, val, (uint64_t) vallen, 0, 0);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
|
||||
clear:
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
@@ -113,17 +126,23 @@ XS(XS_cache_get) {
|
||||
char *key, *val;
|
||||
STRLEN keylen;
|
||||
uint64_t vallen;
|
||||
|
||||
if (uwsgi.cache_max_items == 0) goto clear;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
key = SvPV(ST(0), keylen);
|
||||
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
val = uwsgi_cache_get(key, (uint16_t) keylen, &vallen);
|
||||
|
||||
if (!val)
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
clear:
|
||||
XSRETURN_UNDEF;
|
||||
|
||||
ST(0) = newSVpv(val, vallen);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
sv_2mortal(ST(0));
|
||||
|
||||
XSRETURN(1);
|
||||
@@ -209,5 +228,6 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(log);
|
||||
psgi_xs(async_connect);
|
||||
psgi_xs(suspend);
|
||||
psgi_xs(signal);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import os,sys
|
||||
|
||||
from distutils import sysconfig
|
||||
|
||||
NAME='pypy'
|
||||
GCC_LIST = ['../python/python_plugin', '../python/pyutils', '../python/pyloader', '../python/wsgi_handlers', '../python/wsgi_headers', '../python/wsgi_subhandler',
|
||||
'../python/web3_subhandler', '../python/pump_subhandler','../python/gil', '../python/uwsgi_pymodule', '../python/profiler', '../python/symimporter']
|
||||
|
||||
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
|
||||
CFLAGS.append('-DUWSGI_PYPY')
|
||||
|
||||
LIBS = ['-lpypy-c']
|
||||
LDFLAGS = []
|
||||
@@ -3,14 +3,9 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
void gil_real_get() {}
|
||||
void gil_real_release() {}
|
||||
#else
|
||||
|
||||
void gil_real_get() {
|
||||
//uwsgi_log("LOCK %d\n", uwsgi.mywid);
|
||||
#ifndef PYTHREE
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
PyEval_AcquireLock();
|
||||
PyThreadState_Swap((PyThreadState *) pthread_getspecific(up.upt_gil_key));
|
||||
#else
|
||||
@@ -22,7 +17,7 @@ void gil_real_get() {
|
||||
|
||||
void gil_real_release() {
|
||||
//uwsgi_log("UNLOCK %d\n", uwsgi.mywid);
|
||||
#ifndef PYTHREE
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
pthread_setspecific(up.upt_gil_key, (void *) PyThreadState_Swap(NULL));
|
||||
PyEval_ReleaseLock();
|
||||
#else
|
||||
@@ -31,7 +26,6 @@ void gil_real_release() {
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void gil_fake_get() {}
|
||||
void gil_fake_release() {}
|
||||
|
||||
@@ -16,15 +16,27 @@ int PyFrame_GetLineNumber(PyFrameObject *frame) {
|
||||
int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
static uint64_t last_ts = 0;
|
||||
uint64_t now = uwsgi_micros();
|
||||
uint64_t delta = 0;
|
||||
|
||||
switch(what) {
|
||||
case PyTrace_CALL:
|
||||
uwsgi_log("[uWSGI Python profiler] CALL: %s (line %d) -> %s %d args, stacksize %d\n",
|
||||
if (last_ts == 0) delta = 0;
|
||||
else delta = now - last_ts;
|
||||
last_ts = now;
|
||||
uwsgi_log("[uWSGI Python profiler %llu] CALL: %s (line %d) -> %s %d args, stacksize %d\n",
|
||||
(unsigned long long) delta,
|
||||
PyString_AsString(frame->f_code->co_filename),
|
||||
PyFrame_GetLineNumber(frame),
|
||||
PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount, frame->f_code->co_stacksize);
|
||||
break;
|
||||
case PyTrace_C_CALL:
|
||||
uwsgi_log("[uWSGI Python profiler] C CALL: %s (line %d) -> %s %d args, stacksize %d\n",
|
||||
if (last_ts == 0) delta = 0;
|
||||
else delta = now - last_ts;
|
||||
last_ts = now;
|
||||
uwsgi_log("[uWSGI Python profiler %llu] C CALL: %s (line %d) -> %s %d args, stacksize %d\n",
|
||||
(unsigned long long) delta,
|
||||
PyString_AsString(frame->f_code->co_filename),
|
||||
PyFrame_GetLineNumber(frame),
|
||||
PyEval_GetFuncName(arg), frame->f_code->co_argcount, frame->f_code->co_stacksize);
|
||||
@@ -34,3 +46,26 @@ int uwsgi_python_profiler_call(PyObject *obj, PyFrameObject *frame, int what, Py
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_python_tracer(PyObject *obj, PyFrameObject *frame, int what, PyObject *arg) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
static uint64_t last_ts = 0;
|
||||
uint64_t now = uwsgi_micros();
|
||||
uint64_t delta = 0;
|
||||
|
||||
if (what == PyTrace_LINE) {
|
||||
if (last_ts == 0) {
|
||||
delta = 0;
|
||||
}
|
||||
else {
|
||||
delta = now - last_ts;
|
||||
}
|
||||
last_ts = now;
|
||||
uwsgi_log("[uWSGI Python profiler %llu] file %s line %d: %s argc:%d\n", (unsigned long long)delta, PyString_AsString(frame->f_code->co_filename), PyFrame_GetLineNumber(frame), PyString_AsString(frame->f_code->co_name), frame->f_code->co_argcount);
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -185,8 +185,6 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
|
||||
struct http_status_codes *http_sc;
|
||||
char sc[4];
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// ok its a yield
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
if (PyDict_Check((PyObject *)wsgi_req->async_result)) {
|
||||
@@ -339,7 +337,6 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
#endif
|
||||
@@ -371,22 +368,14 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
Py_DECREF(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
|
||||
clear:
|
||||
if (wsgi_req->async_input) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_input);
|
||||
}
|
||||
if (wsgi_req->async_environ) {
|
||||
PyDict_Clear(wsgi_req->async_environ);
|
||||
}
|
||||
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
|
||||
|
||||
Py_DECREF((PyObject *)wsgi_req->async_result);
|
||||
PyErr_Clear();
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
+65
-36
@@ -86,6 +86,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
time_t now = uwsgi_now();
|
||||
|
||||
mountpoint = uwsgi_strncopy(wsgi_req->appid, wsgi_req->appid_len);
|
||||
|
||||
@@ -375,14 +376,17 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
uwsgi.default_app = id;
|
||||
}
|
||||
|
||||
wi->started_at = now;
|
||||
wi->startup_time = uwsgi_now() - now;
|
||||
|
||||
if (app_type == PYTHON_APP_TYPE_WSGI) {
|
||||
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
|
||||
uwsgi_log( "WSGI app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_WEB3) {
|
||||
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
|
||||
uwsgi_log( "Web3 app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
|
||||
}
|
||||
else if (app_type == PYTHON_APP_TYPE_PUMP) {
|
||||
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
|
||||
uwsgi_log( "Pump app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
|
||||
}
|
||||
|
||||
|
||||
@@ -414,19 +418,15 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
}
|
||||
}
|
||||
|
||||
// check if we need to emulate fork() COW
|
||||
if (uwsgi.mywid == 0) {
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
|
||||
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
|
||||
}
|
||||
}
|
||||
// emulate COW
|
||||
uwsgi_emulate_cow_for_apps(id);
|
||||
|
||||
return id;
|
||||
|
||||
doh:
|
||||
free(mountpoint);
|
||||
PyErr_Print();
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
#ifdef UWSGI_MINTERPRETERS
|
||||
if (interpreter == NULL && id) {
|
||||
Py_EndInterpreter(wi->interpreter);
|
||||
@@ -482,9 +482,7 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
|
||||
|
||||
PyObject *tmp_callable;
|
||||
PyObject *applications;
|
||||
#ifndef UWSGI_PYPY
|
||||
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
|
||||
#endif
|
||||
|
||||
char *module = (char *) arg1;
|
||||
|
||||
@@ -507,11 +505,8 @@ PyObject *uwsgi_uwsgi_loader(void *arg1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
applications = PyDict_GetItemString(uwsgi_dict, "applications");
|
||||
if (applications && PyDict_Check(applications)) return applications;
|
||||
#endif
|
||||
|
||||
|
||||
applications = PyDict_GetItemString(wsgi_dict, "applications");
|
||||
if (applications && PyDict_Check(applications)) return applications;
|
||||
@@ -539,6 +534,7 @@ PyObject *uwsgi_mount_loader(void *arg1) {
|
||||
|
||||
if ( !strcmp(what+strlen(what)-3, ".py") || !strcmp(what+strlen(what)-5, ".wsgi")) {
|
||||
callable = uwsgi_file_loader((void *)what);
|
||||
if (!callable) exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
else if (!strcmp(what+strlen(what)-4, ".ini")) {
|
||||
callable = uwsgi_paste_loader((void *)what);
|
||||
@@ -605,30 +601,44 @@ PyObject *uwsgi_file_loader(void *arg1) {
|
||||
char *callable = up.callable;
|
||||
if (!callable) callable = "application";
|
||||
|
||||
wsgi_file_module = uwsgi_pyimport_by_filename(uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename)), filename);
|
||||
char *py_filename = uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename));
|
||||
|
||||
wsgi_file_module = uwsgi_pyimport_by_filename(py_filename, filename);
|
||||
if (!wsgi_file_module) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
free(py_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wsgi_file_dict = PyModule_GetDict(wsgi_file_module);
|
||||
if (!wsgi_file_dict) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
Py_DECREF(wsgi_file_module);
|
||||
free(py_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, callable);
|
||||
if (!wsgi_file_callable) {
|
||||
PyErr_Print();
|
||||
Py_DECREF(wsgi_file_dict);
|
||||
Py_DECREF(wsgi_file_module);
|
||||
free(py_filename);
|
||||
uwsgi_log( "unable to find \"application\" callable in file %s\n", filename);
|
||||
exit(1);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!PyFunction_Check(wsgi_file_callable) && !PyCallable_Check(wsgi_file_callable)) {
|
||||
uwsgi_log( "\"application\" must be a callable object in file %s\n", filename);
|
||||
exit(1);
|
||||
Py_DECREF(wsgi_file_callable);
|
||||
Py_DECREF(wsgi_file_dict);
|
||||
Py_DECREF(wsgi_file_module);
|
||||
free(py_filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
free(py_filename);
|
||||
|
||||
return wsgi_file_callable;
|
||||
|
||||
}
|
||||
@@ -640,39 +650,58 @@ PyObject *uwsgi_paste_loader(void *arg1) {
|
||||
PyObject *paste_arg, *paste_app;
|
||||
|
||||
uwsgi_log( "Loading paste environment: %s\n", paste);
|
||||
|
||||
if (up.paste_logger) {
|
||||
PyObject *paste_logger_dict = get_uwsgi_pydict("paste.script.util.logging_config");
|
||||
if (paste_logger_dict) {
|
||||
PyObject *paste_logger_fileConfig = PyDict_GetItemString(paste_logger_dict, "fileConfig");
|
||||
if (paste_logger_fileConfig) {
|
||||
PyObject *paste_logger_arg = PyTuple_New(1);
|
||||
if (!paste_logger_arg) {
|
||||
PyErr_Print();
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
PyTuple_SetItem(paste_logger_arg, 0, PyString_FromString(paste+7));
|
||||
if (python_call(paste_logger_fileConfig, paste_logger_arg, 0, NULL)) {
|
||||
PyErr_Print();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
paste_module = PyImport_ImportModule("paste.deploy");
|
||||
if (!paste_module) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
paste_dict = PyModule_GetDict(paste_module);
|
||||
if (!paste_dict) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
paste_loadapp = PyDict_GetItemString(paste_dict, "loadapp");
|
||||
if (!paste_loadapp) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
paste_arg = PyTuple_New(1);
|
||||
if (!paste_arg) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
if (PyTuple_SetItem(paste_arg, 0, PyString_FromString(paste))) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
paste_app = PyEval_CallObject(paste_loadapp, paste_arg);
|
||||
if (!paste_app) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
|
||||
@@ -681,8 +710,10 @@ PyObject *uwsgi_paste_loader(void *arg1) {
|
||||
|
||||
PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
uwsgi_log("the eval loader is currently not supported under PyPy !!!\n");
|
||||
return NULL;
|
||||
#else
|
||||
char *code = (char *) arg1;
|
||||
|
||||
PyObject *wsgi_eval_module, *wsgi_eval_callable = NULL;
|
||||
@@ -694,7 +725,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
if (!wsgi_eval_node) {
|
||||
PyErr_Print();
|
||||
uwsgi_log( "failed to parse <eval> code\n");
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
wsgi_compiled_node = (PyObject *) PyNode_Compile(wsgi_eval_node, "uwsgi_eval_config");
|
||||
@@ -702,14 +733,14 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
if (!wsgi_compiled_node) {
|
||||
PyErr_Print();
|
||||
uwsgi_log( "failed to compile eval code\n");
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
|
||||
wsgi_eval_module = PyImport_ExecCodeModule("uwsgi_eval_config", wsgi_compiled_node);
|
||||
if (!wsgi_eval_module) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
|
||||
@@ -718,7 +749,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
up.loader_dict = PyModule_GetDict(wsgi_eval_module);
|
||||
if (!up.loader_dict) {
|
||||
PyErr_Print();
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
|
||||
|
||||
@@ -733,13 +764,11 @@ PyObject *uwsgi_eval_loader(void *arg1) {
|
||||
if (wsgi_eval_callable) {
|
||||
if (!PyFunction_Check(wsgi_eval_callable) && !PyCallable_Check(wsgi_eval_callable)) {
|
||||
uwsgi_log( "you must define a callable object in your code\n");
|
||||
exit(1);
|
||||
exit(UWSGI_FAILED_APP_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
return wsgi_eval_callable;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
+450
-280
File diff suppressed because it is too large
Load Diff
+138
-23
@@ -8,20 +8,106 @@ int manage_python_response(struct wsgi_request *wsgi_req) {
|
||||
return uwsgi_response_subhandler_wsgi(wsgi_req);
|
||||
}
|
||||
|
||||
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
|
||||
char *uwsgi_python_get_exception_type(PyObject *exc) {
|
||||
char *class_name = NULL;
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
if (PyClass_Check(exc)) {
|
||||
class_name = PyString_AsString( ((PyClassObject*)(exc))->cl_name );
|
||||
}
|
||||
else {
|
||||
#endif
|
||||
class_name = (char *) ((PyTypeObject*)exc)->tp_name;
|
||||
#if !defined(PYTHREE) && !defined(UWSGI_PYPY)
|
||||
}
|
||||
#endif
|
||||
|
||||
PyObject *pyret;
|
||||
if (class_name) {
|
||||
char *dot = strrchr(class_name, '.');
|
||||
if (dot) class_name = dot+1;
|
||||
|
||||
PyObject *module_name = PyObject_GetAttrString(exc, "__module__");
|
||||
if (module_name) {
|
||||
char *mod_name = PyString_AsString(module_name);
|
||||
if (mod_name && strcmp(mod_name, "exceptions") ) {
|
||||
char *ret = uwsgi_concat3(mod_name, ".", class_name);
|
||||
Py_DECREF(module_name);
|
||||
return ret;
|
||||
}
|
||||
Py_DECREF(module_name);
|
||||
return uwsgi_str(class_name);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_python_get_exception_value(PyObject *value) {
|
||||
return PyString_AsString( PyObject_Str(value) );
|
||||
}
|
||||
|
||||
char *uwsgi_python_get_exception_repr(PyObject *exc, PyObject *value) {
|
||||
char *exc_type = uwsgi_python_get_exception_type(exc);
|
||||
char *exc_value = uwsgi_python_get_exception_value(value);
|
||||
|
||||
if (exc_type && exc_value) {
|
||||
return uwsgi_concat3(exc_type, ": ", exc_value);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int uwsgi_python_manage_exceptions(void) {
|
||||
PyObject *type = NULL;
|
||||
PyObject *value = NULL;
|
||||
PyObject *traceback = NULL;
|
||||
|
||||
char *exc_type = NULL;
|
||||
char *exc_value = NULL;
|
||||
char *exc_repr = NULL;
|
||||
|
||||
PyErr_Fetch(&type, &value, &traceback);
|
||||
PyErr_NormalizeException(&type, &value, &traceback);
|
||||
|
||||
if (uwsgi.reload_on_exception_type) {
|
||||
exc_type = uwsgi_python_get_exception_type(type);
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_exception_value) {
|
||||
exc_value = uwsgi_python_get_exception_value(value);
|
||||
}
|
||||
|
||||
if (uwsgi.reload_on_exception_repr) {
|
||||
exc_repr = uwsgi_python_get_exception_repr(type, value);
|
||||
}
|
||||
|
||||
int ret = uwsgi_manage_exception(exc_type, exc_value, exc_repr);
|
||||
|
||||
// free memory allocated for strcmp
|
||||
if (exc_type) free(exc_type);
|
||||
if (exc_repr) free(exc_repr);
|
||||
|
||||
PyErr_Restore(type, value, traceback);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi_request *wsgi_req) {
|
||||
|
||||
//uwsgi_log("ready to call %p %p\n", callable, args);
|
||||
|
||||
pyret = PyEval_CallObject(callable, args);
|
||||
PyObject *pyret = PyEval_CallObject(callable, args);
|
||||
|
||||
//uwsgi_log("called\n");
|
||||
|
||||
if (PyErr_Occurred()) {
|
||||
|
||||
|
||||
int do_exit = uwsgi_python_manage_exceptions();
|
||||
|
||||
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
|
||||
uwsgi_log("Memory Error detected !!!\n");
|
||||
}
|
||||
|
||||
// this can be in a spooler or in the master
|
||||
if (uwsgi.mywid > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].exceptions++;
|
||||
@@ -32,6 +118,10 @@ PyObject *python_call(PyObject *callable, PyObject *args, int catch, struct wsgi
|
||||
if (!catch) {
|
||||
PyErr_Print();
|
||||
}
|
||||
|
||||
if (do_exit) {
|
||||
exit(UWSGI_EXCEPTION_CODE);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -64,32 +154,60 @@ void init_pyargv() {
|
||||
|
||||
char *ap;
|
||||
|
||||
char *argv0 = "uwsgi";
|
||||
|
||||
if (up.pyrun) {
|
||||
argv0 = up.pyrun;
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
wchar_t pname[6];
|
||||
mbstowcs(pname, "uwsgi", 6);
|
||||
up.py_argv[0] = pname;
|
||||
wchar_t *pname = uwsgi_calloc(sizeof(wchar_t) * (strlen(argv0)+1));
|
||||
mbstowcs(pname, argv0, strlen(argv0)+1);
|
||||
#else
|
||||
up.py_argv[0] = "uwsgi";
|
||||
char *pname = argv0;
|
||||
#endif
|
||||
|
||||
up.argc = 1;
|
||||
|
||||
if (up.argv != NULL) {
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
|
||||
if (!wcargv) {
|
||||
uwsgi_error("malloc()");
|
||||
exit(1);
|
||||
if (up.argv) {
|
||||
char *tmp_ptr = uwsgi_str(up.argv);
|
||||
#ifdef __sun__
|
||||
// FIX THIS !!!
|
||||
ap = strtok(tmp_ptr, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&tmp_ptr, " \t")) != NULL) {
|
||||
#endif
|
||||
if (*ap != '\0') {
|
||||
up.argc++;
|
||||
}
|
||||
}
|
||||
memset(wcargv, 0, sizeof( wchar_t ) * (strlen(up.argv)+1));
|
||||
|
||||
free(tmp_ptr);
|
||||
}
|
||||
|
||||
#ifdef PYTHREE
|
||||
up.py_argv = uwsgi_calloc(sizeof(wchar_t *) * up.argc+1);
|
||||
#else
|
||||
up.py_argv = uwsgi_calloc(sizeof(char *) * up.argc+1);
|
||||
#endif
|
||||
|
||||
up.py_argv[0] = pname;
|
||||
|
||||
|
||||
if (up.argv) {
|
||||
|
||||
char *py_argv_copy = uwsgi_str(up.argv);
|
||||
up.argc = 1;
|
||||
#ifdef PYTHREE
|
||||
wchar_t *wcargv = uwsgi_calloc( sizeof( wchar_t ) * (strlen(py_argv_copy)+1));
|
||||
#endif
|
||||
|
||||
#ifdef __sun__
|
||||
// FIX THIS !!!
|
||||
ap = strtok(up.argv, " ");
|
||||
ap = strtok(py_argv_copy, " ");
|
||||
while ((ap = strtok(NULL, " ")) != NULL) {
|
||||
#else
|
||||
while ((ap = strsep(&up.argv, " \t")) != NULL) {
|
||||
while ((ap = strsep(&py_argv_copy, " \t")) != NULL) {
|
||||
#endif
|
||||
if (*ap != '\0') {
|
||||
#ifdef PYTHREE
|
||||
@@ -100,14 +218,11 @@ void init_pyargv() {
|
||||
#endif
|
||||
up.argc++;
|
||||
}
|
||||
if (up.argc + 1 > MAX_PYARGV)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
PySys_SetArgv(up.argc, up.py_argv);
|
||||
#endif
|
||||
}
|
||||
|
||||
PySys_SetArgv(up.argc, up.py_argv);
|
||||
|
||||
PyObject *sys_dict = get_uwsgi_pydict("sys");
|
||||
if (!sys_dict) {
|
||||
|
||||
+303
-125
@@ -148,24 +148,14 @@ char *uwsgi_encode_pydict(PyObject * pydict, uint16_t * size) {
|
||||
keysize = PyString_Size(key);
|
||||
valsize = PyString_Size(val);
|
||||
if (bufptr + keysize + 2 + valsize + 2 <= buf + *size) {
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keysize = uwsgi_swap16(keysize);
|
||||
#endif
|
||||
memcpy(bufptr, &keysize, 2);
|
||||
bufptr += 2;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keysize = uwsgi_swap16(keysize);
|
||||
#endif
|
||||
|
||||
*bufptr++ = (uint8_t) (keysize & 0xff);
|
||||
*bufptr++ = (uint8_t) ((keysize >> 8) & 0xff);
|
||||
memcpy(bufptr, PyString_AsString(key), keysize);
|
||||
bufptr += keysize;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
valsize = uwsgi_swap16(valsize);
|
||||
#endif
|
||||
memcpy(bufptr, &valsize, 2);
|
||||
bufptr += 2;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
valsize = uwsgi_swap16(valsize);
|
||||
#endif
|
||||
|
||||
*bufptr++ = (uint8_t) (valsize & 0xff);
|
||||
*bufptr++ = (uint8_t) ((valsize >> 8) & 0xff);
|
||||
memcpy(bufptr, PyString_AsString(val), valsize);
|
||||
bufptr += valsize;
|
||||
}
|
||||
@@ -181,7 +171,7 @@ char *uwsgi_encode_pydict(PyObject * pydict, uint16_t * size) {
|
||||
PyObject *py_uwsgi_listen_queue(PyObject * self, PyObject * args) {
|
||||
|
||||
#ifdef __linux__
|
||||
return PyInt_FromLong(uwsgi.shared->ti.tcpi_unacked);
|
||||
return PyInt_FromLong(uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS]);
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
@@ -322,7 +312,9 @@ PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
|
||||
argvs[i] = PyString_Size(py_str);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
char *response = uwsgi_do_rpc(NULL, func, argc - 1, argv, argvs, &size);
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
if (size > 0) {
|
||||
PyObject *ret = PyString_FromStringAndSize(response, size);
|
||||
@@ -391,7 +383,9 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
|
||||
argvs[i] = PyString_Size(py_str);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL;
|
||||
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
if (size > 0) {
|
||||
PyObject *ret = PyString_FromStringAndSize(response, size);
|
||||
@@ -894,7 +888,7 @@ PyObject *py_uwsgi_log(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *py_uwsgi_i_am_the_spooler(PyObject * self, PyObject * args) {
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
@@ -904,13 +898,47 @@ PyObject *py_uwsgi_i_am_the_spooler(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_is_locked(PyObject * self, PyObject * args) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
// the spooler cannot lock resources
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|i:is_locked", &lock_num)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (lock_num < 0 || lock_num > uwsgi.locks) {
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid lock number");
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
if (uwsgi_lock_check(uwsgi.user_lock[lock_num]) == 0) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_False);
|
||||
return Py_False;
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_lock(PyObject * self, PyObject * args) {
|
||||
|
||||
int lock_num = 0;
|
||||
|
||||
// the spooler cannot lock resources
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
|
||||
}
|
||||
#endif
|
||||
@@ -923,7 +951,9 @@ PyObject *py_uwsgi_lock(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid lock number");
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_lock(uwsgi.user_lock[lock_num]);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
@@ -934,7 +964,7 @@ PyObject *py_uwsgi_unlock(PyObject * self, PyObject * args) {
|
||||
int lock_num = 0;
|
||||
|
||||
#ifdef UWSGI_SPOOLER
|
||||
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
|
||||
if (uwsgi.i_am_a_spooler) {
|
||||
return PyErr_Format(PyExc_ValueError, "The spooler cannot lock/unlock resources");
|
||||
}
|
||||
#endif
|
||||
@@ -947,7 +977,6 @@ PyObject *py_uwsgi_unlock(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_ValueError, "Invalid lock number");
|
||||
}
|
||||
|
||||
|
||||
uwsgi_unlock(uwsgi.user_lock[lock_num]);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -1045,7 +1074,9 @@ PyObject *py_uwsgi_farm_msg(PyObject * self, PyObject * args) {
|
||||
for(i=0;i<uwsgi.farms_cnt;i++) {
|
||||
|
||||
if (!strcmp(farm_name, uwsgi.farms[i].name)) {
|
||||
UWSGI_RELEASE_GIL
|
||||
len = write(uwsgi.farms[i].queue_pipe[0], message, message_len);
|
||||
UWSGI_GET_GIL
|
||||
if (len <= 0) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
@@ -1076,7 +1107,9 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_ValueError, "no mule configured");
|
||||
|
||||
if (mule_obj == NULL) {
|
||||
UWSGI_RELEASE_GIL
|
||||
mule_send_msg(uwsgi.shared->mule_queue_pipe[0], message, message_len);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
else {
|
||||
if (PyString_Check(mule_obj)) {
|
||||
@@ -1103,7 +1136,9 @@ PyObject *py_uwsgi_mule_msg(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (fd > -1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
mule_send_msg(fd, message, message_len);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1248,6 +1283,8 @@ PyObject *py_uwsgi_sharedarea_inclong(PyObject * self, PyObject * args) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
@@ -1255,11 +1292,10 @@ PyObject *py_uwsgi_sharedarea_inclong(PyObject * self, PyObject * args) {
|
||||
value = current_value + value;
|
||||
memcpy(uwsgi.sharedarea + pos, &value, 8);
|
||||
|
||||
PyObject *ret = PyInt_FromLong(value);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return ret;
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1281,16 +1317,17 @@ PyObject *py_uwsgi_sharedarea_writelong(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
memcpy(uwsgi.sharedarea + pos, &value, 8);
|
||||
|
||||
|
||||
PyObject *ret = PyInt_FromLong(value);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
return ret;
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1313,15 +1350,19 @@ PyObject *py_uwsgi_sharedarea_write(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
memcpy(uwsgi.sharedarea + pos, value, value_len);
|
||||
|
||||
PyObject *ret = PyInt_FromLong(value_len);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value_len);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@@ -1344,15 +1385,18 @@ PyObject *py_uwsgi_sharedarea_writebyte(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
uwsgi.sharedarea[pos] = value;
|
||||
|
||||
PyObject *ret = PyInt_FromLong(uwsgi.sharedarea[pos]);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
return ret;
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1374,15 +1418,18 @@ PyObject *py_uwsgi_sharedarea_readlong(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
memcpy(&value, uwsgi.sharedarea + pos, 8);
|
||||
|
||||
PyObject *ret = PyLong_FromLong(value);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
return ret;
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyLong_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1404,13 +1451,17 @@ PyObject *py_uwsgi_sharedarea_readbyte(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
PyObject *ret = PyInt_FromLong(uwsgi.sharedarea[pos]);
|
||||
char value = uwsgi.sharedarea[pos];
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
return ret;
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
@@ -1432,12 +1483,23 @@ PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *ret = PyString_FromStringAndSize(NULL, len);
|
||||
#ifdef PYTHREE
|
||||
char *storage = PyBytes_AsString(ret);
|
||||
#else
|
||||
char *storage = PyString_AS_STRING(ret);
|
||||
#endif
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
PyObject *ret = PyString_FromStringAndSize(uwsgi.sharedarea + pos, len);
|
||||
memcpy(storage, uwsgi.sharedarea + pos, len);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1462,23 +1524,25 @@ PyObject *py_uwsgi_spooler_jobs(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *jobslist = PyList_New(0);
|
||||
|
||||
sdir = opendir(uwsgi.spool_dir);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
|
||||
sdir = opendir(uspool->dir);
|
||||
|
||||
if (sdir) {
|
||||
while ((dp = readdir(sdir)) != NULL) {
|
||||
if (!strncmp("uwsgi_spoolfile_on_", dp->d_name, 19)) {
|
||||
abs_path = malloc(strlen(uwsgi.spool_dir) + 1 + strlen(dp->d_name) + 1);
|
||||
abs_path = malloc(strlen(uspool->dir) + 1 + strlen(dp->d_name) + 1);
|
||||
if (!abs_path) {
|
||||
uwsgi_error("malloc()");
|
||||
closedir(sdir);
|
||||
goto clear;
|
||||
}
|
||||
|
||||
memset(abs_path, 0, strlen(uwsgi.spool_dir) + 1 + strlen(dp->d_name) + 1);
|
||||
memset(abs_path, 0, strlen(uspool->dir) + 1 + strlen(dp->d_name) + 1);
|
||||
|
||||
memcpy(abs_path, uwsgi.spool_dir, strlen(uwsgi.spool_dir));
|
||||
memcpy(abs_path + strlen(uwsgi.spool_dir), "/", 1);
|
||||
memcpy(abs_path + strlen(uwsgi.spool_dir) + 1, dp->d_name, strlen(dp->d_name));
|
||||
memcpy(abs_path, uspool->dir, strlen(uspool->dir));
|
||||
memcpy(abs_path + strlen(uspool->dir), "/", 1);
|
||||
memcpy(abs_path + strlen(uspool->dir) + 1, dp->d_name, strlen(dp->d_name));
|
||||
|
||||
|
||||
if (lstat(abs_path, &sf_lstat)) {
|
||||
@@ -1520,6 +1584,8 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
char *body = NULL;
|
||||
size_t body_len= 0;
|
||||
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
|
||||
spool_dict = PyTuple_GetItem(args, 0);
|
||||
|
||||
if (spool_dict) {
|
||||
@@ -1539,6 +1605,17 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
return PyErr_Format(PyExc_ValueError, "The argument of spooler callable must be a dictionary");
|
||||
}
|
||||
|
||||
// TODO if "spooler" is a num, get the spooler by id, otherwise get it by directory
|
||||
PyObject *py_spooler = uwsgi_py_dict_get(spool_dict, "spooler");
|
||||
if (py_spooler) {
|
||||
if (PyString_Check(py_spooler)) {
|
||||
uspool = uwsgi_get_spooler_by_name(PyString_AsString(py_spooler));
|
||||
if (!uspool) {
|
||||
return PyErr_Format(PyExc_ValueError, "Unknown spooler requested");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PyObject *pyprio = uwsgi_py_dict_get(spool_dict, "priority");
|
||||
if (pyprio) {
|
||||
if (PyInt_Check(pyprio)) {
|
||||
@@ -1600,24 +1677,15 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
valsize = PyString_Size(val);
|
||||
if (cur_buf + keysize + 2 + valsize + 2 <= spool_buffer + UMAX16) {
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keysize = uwsgi_swap16(keysize);
|
||||
#endif
|
||||
memcpy(cur_buf, &keysize, 2);
|
||||
cur_buf += 2;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
keysize = uwsgi_swap16(keysize);
|
||||
#endif
|
||||
*cur_buf++ = (uint8_t) (keysize & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((keysize >> 8) & 0xff);
|
||||
|
||||
memcpy(cur_buf, PyString_AsString(key), keysize);
|
||||
cur_buf += keysize;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
valsize = uwsgi_swap16(valsize);
|
||||
#endif
|
||||
memcpy(cur_buf, &valsize, 2);
|
||||
cur_buf += 2;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
valsize = uwsgi_swap16(valsize);
|
||||
#endif
|
||||
|
||||
*cur_buf++ = (uint8_t) (valsize & 0xff);
|
||||
*cur_buf++ = (uint8_t) ((valsize >> 8) & 0xff);
|
||||
|
||||
memcpy(cur_buf, PyString_AsString(val), valsize);
|
||||
cur_buf += valsize;
|
||||
}
|
||||
@@ -1647,16 +1715,20 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
}
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
if (numprio) {
|
||||
priority = uwsgi_num2str(numprio);
|
||||
}
|
||||
i = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
|
||||
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, cur_buf - spool_buffer, priority, at, body, body_len);
|
||||
if (priority) {
|
||||
free(priority);
|
||||
}
|
||||
|
||||
free(spool_buffer);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
Py_DECREF(spool_vars);
|
||||
|
||||
if (i > 0) {
|
||||
@@ -1670,7 +1742,9 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_spooler_pid(PyObject * self, PyObject * args) {
|
||||
return PyInt_FromLong(uwsgi.shared->spooler_pid ? uwsgi.shared->spooler_pid : 0);
|
||||
struct uwsgi_spooler *uspool = uwsgi.spoolers;
|
||||
if (!uwsgi.spoolers) return PyInt_FromLong(0);
|
||||
return PyInt_FromLong(uspool->pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -1866,24 +1940,6 @@ PyObject *py_uwsgi_set_option(PyObject * self, PyObject * args) {
|
||||
return PyInt_FromLong(value);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_load_plugin(PyObject * self, PyObject * args) {
|
||||
int modifier;
|
||||
char *plugin_name = NULL;
|
||||
char *pargs = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "is|s:load_plugin", &modifier, &plugin_name, &pargs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi_load_plugin(modifier, plugin_name, pargs, 1)) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MULTICAST
|
||||
PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
|
||||
|
||||
@@ -1898,7 +1954,9 @@ PyObject *py_uwsgi_multicast(PyObject * self, PyObject * args) {
|
||||
|
||||
uwsgi_message = uwsgi_malloc(message_len+4);
|
||||
memcpy(uwsgi_message+4, message, message_len);
|
||||
UWSGI_RELEASE_GIL
|
||||
ret = send_udp_message(UWSGI_MODIFIER_MULTICAST, 0, host, uwsgi_message, message_len);
|
||||
UWSGI_GET_GIL
|
||||
free(uwsgi_message);
|
||||
|
||||
if (ret <= 0) {
|
||||
@@ -2268,9 +2326,12 @@ PyObject *py_uwsgi_route(PyObject * self, PyObject * args) {
|
||||
return PyErr_Format(PyExc_IOError, "unable to connect to host %s", addr);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_send_message(uwsgi_fd, wsgi_req->uh.modifier1, wsgi_req->uh.modifier2, wsgi_req->buffer, wsgi_req->uh.pktsize, wsgi_req->poll.fd, wsgi_req->post_cl, 0) < 0) {
|
||||
UWSGI_GET_GIL
|
||||
return PyErr_Format(PyExc_IOError, "unable to send uwsgi request to host %s", addr);
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// request sent, return the iterator response
|
||||
uwsgi_Iter *ui = PyObject_New(uwsgi_Iter, &uwsgi_IterType);
|
||||
@@ -2320,7 +2381,9 @@ PyObject *py_uwsgi_send_message(PyObject * self, PyObject * args) {
|
||||
uwsgi_fd = PyInt_AsLong(destination);
|
||||
}
|
||||
else if (PyString_Check(destination)) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_fd = uwsgi_connect(PyString_AsString(destination), timeout, 0);
|
||||
UWSGI_GET_GIL
|
||||
close_fd = 1;
|
||||
}
|
||||
|
||||
@@ -2457,7 +2520,7 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
zero = PyString_FromString("cheap");
|
||||
}
|
||||
else if (uwsgi.workers[i + 1].suspended) {
|
||||
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
|
||||
zero = PyString_FromString("pause");
|
||||
}
|
||||
else {
|
||||
@@ -2533,6 +2596,8 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
|
||||
PyDict_SetItemString(apps_dict, "mountpoint", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
PyDict_SetItemString(apps_dict, "startup_time", PyInt_FromLong((long) ua->startup_time));
|
||||
|
||||
PyDict_SetItemString(apps_dict, "interpreter", PyInt_FromLong((long)ua->interpreter));
|
||||
PyDict_SetItemString(apps_dict, "callable", PyInt_FromLong((long)ua->interpreter));
|
||||
|
||||
@@ -2682,30 +2747,38 @@ PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
fd = open(filename, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
UWSGI_GET_GIL
|
||||
goto clear;
|
||||
}
|
||||
|
||||
len = read(fd, &uh, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("read()");
|
||||
UWSGI_GET_GIL
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
buffer = malloc(uh.pktsize);
|
||||
if (!buffer) {
|
||||
uwsgi_error("malloc()");
|
||||
UWSGI_GET_GIL
|
||||
goto clear2;
|
||||
}
|
||||
len = read(fd, buffer, uh.pktsize);
|
||||
if (len != uh.pktsize) {
|
||||
uwsgi_error("read()");
|
||||
free(buffer);
|
||||
UWSGI_GET_GIL
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
ptrbuf = buffer;
|
||||
bufferend = ptrbuf + uh.pktsize;
|
||||
|
||||
@@ -2794,12 +2867,15 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
|
||||
uwsgi_error("fork()");
|
||||
goto clear;
|
||||
}
|
||||
// now i am a grunt, avoid it making mess
|
||||
else if (grunt_pid == 0) {
|
||||
// it will no more accepts requests
|
||||
uwsgi_close_all_sockets();
|
||||
// create a new session
|
||||
setsid();
|
||||
// exit on SIGPIPE
|
||||
signal(SIGPIPE, (void *) &end_me);
|
||||
// here we create a new worker. Each grunt will race on this datas, so do not rely on them
|
||||
uwsgi.mywid = uwsgi.numproc + 1;
|
||||
uwsgi.mypid = getpid();
|
||||
memset(&uwsgi.workers[uwsgi.mywid], 0, sizeof(struct uwsgi_worker));
|
||||
@@ -2816,7 +2892,7 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
// close connection on the worker
|
||||
// close connection on the original worker
|
||||
if (PyTuple_Size(args) == 0) {
|
||||
if (wsgi_req->socket) {
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
@@ -2958,8 +3034,8 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"log_this_request", py_uwsgi_log_this, METH_VARARGS, ""},
|
||||
{"disconnect", py_uwsgi_disconnect, METH_VARARGS, ""},
|
||||
{"grunt", py_uwsgi_grunt, METH_VARARGS, ""},
|
||||
{"load_plugin", py_uwsgi_load_plugin, METH_VARARGS, ""},
|
||||
{"lock", py_uwsgi_lock, METH_VARARGS, ""},
|
||||
{"is_locked", py_uwsgi_is_locked, METH_VARARGS, ""},
|
||||
{"unlock", py_uwsgi_unlock, METH_VARARGS, ""},
|
||||
{"cl", py_uwsgi_cl, METH_VARARGS, ""},
|
||||
|
||||
@@ -3055,16 +3131,21 @@ PyObject *py_uwsgi_cache_del(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_send_string(remote, 111, 2, key, keylen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
else if (uwsgi.cache_max_items) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_del(key, keylen)) {
|
||||
if (uwsgi_cache_del(key, keylen, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
@@ -3092,16 +3173,21 @@ PyObject *py_uwsgi_cache_set(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_send_string2(remote, 111, 1, key, keylen, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
else if (uwsgi.cache_max_items) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
@@ -3128,16 +3214,21 @@ PyObject *py_uwsgi_cache_update(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_send_string2(remote, 111, 1, key, keylen, value, vallen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
else if (uwsgi.cache_max_items) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
Py_INCREF(Py_True);
|
||||
@@ -3162,15 +3253,25 @@ PyObject *py_uwsgi_cache_exists(PyObject * self, PyObject * args) {
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
// TODO FIX THIS !!!
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_message_string(remote, 111, 0, key, keylen, buffer, &valsize, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
if (valsize > 0) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
}
|
||||
else if (uwsgi_cache_exists(key, keylen)) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
else if (uwsgi.cache_max_items) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
if (uwsgi_cache_exists(key, keylen)) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -3189,16 +3290,20 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
if (uwsgi_queue_push(message, msglen)) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
res = Py_True;
|
||||
}
|
||||
else {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3219,16 +3324,20 @@ PyObject *py_uwsgi_queue_set(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
if (uwsgi_queue_set(pos, message, msglen)) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
res = Py_True;
|
||||
}
|
||||
else {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3254,18 +3363,29 @@ PyObject *py_uwsgi_queue_pull(PyObject * self, PyObject * args) {
|
||||
char *message;
|
||||
uint64_t size;
|
||||
PyObject *res;
|
||||
char *storage;
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
|
||||
message = uwsgi_queue_pull(&size);
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
}
|
||||
else {
|
||||
|
||||
if (!message || size == 0) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
storage = uwsgi_malloc(size);
|
||||
memcpy(storage, message, size);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
res = PyString_FromStringAndSize(storage, size);
|
||||
free(storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3279,18 +3399,29 @@ PyObject *py_uwsgi_queue_pop(PyObject * self, PyObject * args) {
|
||||
char *message;
|
||||
uint64_t size;
|
||||
PyObject *res;
|
||||
char *storage;
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_wlock(uwsgi.queue_lock);
|
||||
|
||||
message = uwsgi_queue_pop(&size);
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
}
|
||||
else {
|
||||
if (!message || size == 0) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
storage = uwsgi_malloc(size);
|
||||
memcpy(storage, message, size);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
res = PyString_FromStringAndSize(storage, size);
|
||||
free(storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3306,22 +3437,32 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
|
||||
uint64_t size = 0;
|
||||
char *message;
|
||||
PyObject *res;
|
||||
char *storage;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l:queue_get", &index)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (uwsgi.queue_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.queue_lock);
|
||||
|
||||
message = uwsgi_queue_get(index, &size);
|
||||
if (message && size > 0) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
if (!message || size == 0) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
storage = uwsgi_malloc(size);
|
||||
memcpy(storage, message, size);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
res = PyString_FromStringAndSize(storage, size);
|
||||
free(storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3331,11 +3472,12 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
|
||||
|
||||
PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
|
||||
long num = 0;
|
||||
long i, num = 0;
|
||||
uint64_t size = 0;
|
||||
char *message;
|
||||
PyObject *res = NULL, *zero;
|
||||
PyObject *res = NULL;
|
||||
uint64_t base;
|
||||
char *storage;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "|l:queue_last", &num)) {
|
||||
return NULL;
|
||||
@@ -3347,6 +3489,7 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
res = PyList_New(0);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.queue_lock);
|
||||
|
||||
if (uwsgi.queue_header->pos > 0) {
|
||||
@@ -3358,31 +3501,41 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
|
||||
if (num == 0) {
|
||||
message = uwsgi_queue_get(base, &size);
|
||||
if (message && size) {
|
||||
res = PyString_FromStringAndSize(message, size);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
res = Py_None;
|
||||
}
|
||||
if (!message || size == 0) {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
storage = uwsgi_malloc(size);
|
||||
memcpy(storage, message, size);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
res = PyString_FromStringAndSize(storage, size);
|
||||
free(storage);
|
||||
return res;
|
||||
}
|
||||
|
||||
if (num > (long)uwsgi.queue_size) num = uwsgi.queue_size;
|
||||
|
||||
char **queue_items = uwsgi_malloc(sizeof(char *) * num);
|
||||
uint64_t *queue_items_size = uwsgi_malloc(sizeof(uint64_t) * num);
|
||||
long item_pos = 0;
|
||||
while(num) {
|
||||
message = uwsgi_queue_get(base, &size);
|
||||
if (message && size) {
|
||||
zero = PyString_FromStringAndSize(message, size);
|
||||
PyList_Append(res, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
else {
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
return res;
|
||||
if (!message || size == 0) {
|
||||
queue_items[item_pos] = NULL;
|
||||
queue_items_size[item_pos] = 0;
|
||||
}
|
||||
else {
|
||||
queue_items[item_pos] = uwsgi_malloc(size);
|
||||
memcpy(queue_items[item_pos], message, size);
|
||||
queue_items_size[item_pos] = size;
|
||||
}
|
||||
item_pos++;
|
||||
if (base > 0) {
|
||||
base--;
|
||||
}
|
||||
@@ -3391,7 +3544,24 @@ PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
|
||||
}
|
||||
num--;
|
||||
}
|
||||
|
||||
uwsgi_rwunlock(uwsgi.queue_lock);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
for(i=0;i<item_pos;i++) {
|
||||
if (queue_items[i]) {
|
||||
PyObject *zero = PyString_FromStringAndSize(queue_items[i], queue_items_size[i]);
|
||||
PyList_Append(res, zero);
|
||||
Py_DECREF(zero);
|
||||
free(queue_items[i]);
|
||||
}
|
||||
else {
|
||||
Py_INCREF(Py_None);
|
||||
PyList_Append(res, Py_None);
|
||||
}
|
||||
}
|
||||
free(queue_items);
|
||||
free(queue_items_size);
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -3409,7 +3579,7 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
char *value = NULL;
|
||||
char *remote = NULL;
|
||||
char buffer[0xffff];
|
||||
PyObject *res;
|
||||
PyObject *ret;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
struct timeval tv, tv2;
|
||||
@@ -3420,7 +3590,9 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
if (remote && strlen(remote) > 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_simple_message_string(remote, 111, 0, key, keylen, buffer, &valsize16, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
UWSGI_GET_GIL
|
||||
if (valsize16 > 0) {
|
||||
value = buffer;
|
||||
valsize = valsize16;
|
||||
@@ -3430,22 +3602,28 @@ PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
gettimeofday(&tv, NULL);
|
||||
#endif
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_rlock(uwsgi.cache_lock);
|
||||
value = uwsgi_cache_get(key, keylen, &valsize);
|
||||
if (!value) {
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
res = PyString_FromStringAndSize(value, valsize);
|
||||
char *storage = uwsgi_malloc(valsize);
|
||||
#ifdef UWSGI_DEBUG
|
||||
gettimeofday(&tv2, NULL);
|
||||
if ((tv2.tv_sec* (1000*1000) + tv2.tv_usec) - (tv.tv_sec* (1000*1000) + tv.tv_usec) > 30000) {
|
||||
uwsgi_log("[slow] cache get done in %d microseconds (%llu bytes value)\n", (tv2.tv_sec* (1000*1000) + tv2.tv_usec) - (tv.tv_sec* (1000*1000) + tv.tv_usec), (unsigned long long) valsize);
|
||||
}
|
||||
#endif
|
||||
memcpy(storage, value, valsize);
|
||||
uwsgi_rwunlock(uwsgi.cache_lock);
|
||||
return res;
|
||||
UWSGI_GET_GIL
|
||||
ret = PyString_FromStringAndSize(storage, valsize);
|
||||
free(storage);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
|
||||
@@ -3,26 +3,6 @@
|
||||
|
||||
#include <frameobject.h>
|
||||
|
||||
#define MAX_PYMODULE_ALIAS 64
|
||||
#define MAX_PYARGV 10
|
||||
|
||||
#define LONG_ARGS_PYTHON_BASE 17000 + ((0 + 1) * 1000)
|
||||
|
||||
#define LONG_ARGS_PYTHONPATH LONG_ARGS_PYTHON_BASE + 1
|
||||
#define LONG_ARGS_PASTE LONG_ARGS_PYTHON_BASE + 2
|
||||
#define LONG_ARGS_PYARGV LONG_ARGS_PYTHON_BASE + 3
|
||||
#define LONG_ARGS_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 4
|
||||
#define LONG_ARGS_RELOAD_OS_ENV LONG_ARGS_PYTHON_BASE + 5
|
||||
#define LONG_ARGS_PYIMPORT LONG_ARGS_PYTHON_BASE + 6
|
||||
#define LONG_ARGS_POST_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 7
|
||||
#define LONG_ARGS_WEB3 LONG_ARGS_PYTHON_BASE + 8
|
||||
#define LONG_ARGS_PUMP LONG_ARGS_PYTHON_BASE + 9
|
||||
#define LONG_ARGS_WSGI_LITE LONG_ARGS_PYTHON_BASE + 10
|
||||
#define LONG_ARGS_PYSHELL LONG_ARGS_PYTHON_BASE + 11
|
||||
#define LONG_ARGS_SPOOLER_PYIMPORT LONG_ARGS_PYTHON_BASE + 12
|
||||
#define LONG_ARGS_PYTHON_RUN LONG_ARGS_PYTHON_BASE + 13
|
||||
#define LONG_ARGS_SHARED_PYIMPORT LONG_ARGS_PYTHON_BASE + 14
|
||||
|
||||
#define PYTHON_APP_TYPE_WSGI 0
|
||||
#define PYTHON_APP_TYPE_WEB3 1
|
||||
#define PYTHON_APP_TYPE_WSGI2 2
|
||||
@@ -58,6 +38,14 @@
|
||||
#define PyVarObject_HEAD_INIT(x, y) PyObject_HEAD_INIT(x) y,
|
||||
#endif
|
||||
|
||||
#define uwsgi_py_write_set_exception(x) PyErr_SetString(PyExc_IOError, "write error");
|
||||
#define uwsgi_py_write_exception(x) uwsgi_py_write_set_exception(x); PyErr_Print();
|
||||
|
||||
|
||||
#define uwsgi_py_check_write_errors if (wsgi_req->write_errors > 0 && uwsgi.write_errors_exception_only) {\
|
||||
uwsgi_py_write_set_exception(wsgi_req);\
|
||||
}\
|
||||
else if (wsgi_req->write_errors > uwsgi.write_errors_tolerance)\
|
||||
|
||||
PyAPI_FUNC(PyObject *) PyMarshal_WriteObjectToString(PyObject *, int);
|
||||
PyAPI_FUNC(PyObject *) PyMarshal_ReadObjectFromString(char *, Py_ssize_t);
|
||||
@@ -118,9 +106,9 @@ struct uwsgi_python {
|
||||
int argc;
|
||||
|
||||
#ifdef PYTHREE
|
||||
wchar_t *py_argv[MAX_PYARGV];
|
||||
wchar_t **py_argv;
|
||||
#else
|
||||
char *py_argv[MAX_PYARGV];
|
||||
char **py_argv;
|
||||
#endif
|
||||
|
||||
PyObject *wsgi_spitout;
|
||||
@@ -131,12 +119,15 @@ struct uwsgi_python {
|
||||
char *test_module;
|
||||
|
||||
int pyshell;
|
||||
int pyshell_oneshot;
|
||||
|
||||
|
||||
struct uwsgi_string_list *python_path;
|
||||
struct uwsgi_string_list *import_list;
|
||||
struct uwsgi_string_list *shared_import_list;
|
||||
struct uwsgi_string_list *spooler_import_list;
|
||||
struct uwsgi_string_list *post_pymodule_alias;
|
||||
struct uwsgi_string_list *pymodule_alias;
|
||||
|
||||
PyObject *loader_dict;
|
||||
PyObject* (*loaders[LOADER_MAX]) (void *);
|
||||
@@ -144,6 +135,7 @@ struct uwsgi_python {
|
||||
char *wsgi_config;
|
||||
char *file_config;
|
||||
char *paste;
|
||||
int paste_logger;
|
||||
char *eval;
|
||||
|
||||
char *web3;
|
||||
@@ -152,9 +144,6 @@ struct uwsgi_python {
|
||||
|
||||
char *callable;
|
||||
|
||||
int ignore_script_name;
|
||||
int catch_exceptions;
|
||||
|
||||
int *current_recursion_depth;
|
||||
struct _frame **current_frame;
|
||||
|
||||
@@ -170,15 +159,14 @@ struct uwsgi_python {
|
||||
pthread_mutex_t lock_pyloaders;
|
||||
void (*gil_get) (void);
|
||||
void (*gil_release) (void);
|
||||
int auto_reload;
|
||||
struct uwsgi_string_list *auto_reload_ignore;
|
||||
#endif
|
||||
|
||||
PyObject *workers_tuple;
|
||||
PyObject *embedded_dict;
|
||||
PyObject *embedded_args;
|
||||
PyObject *fastfuncslist;
|
||||
|
||||
char *pymodule_alias[MAX_PYMODULE_ALIAS];
|
||||
int pymodule_alias_cnt;
|
||||
|
||||
int pep3333_input;
|
||||
|
||||
@@ -186,6 +174,11 @@ struct uwsgi_python {
|
||||
|
||||
int reload_os_env;
|
||||
|
||||
PyObject *after_req_hook;
|
||||
PyObject *after_req_hook_args;
|
||||
|
||||
char *pyrun;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -259,14 +252,20 @@ PyObject *uwsgi_pyimport_by_filename(char *, char *);
|
||||
|
||||
void threaded_swap_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void simple_swap_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void simple_threaded_swap_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void simple_reset_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
void simple_threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
|
||||
|
||||
int uwsgi_python_profiler_call(PyObject *, PyFrameObject *, int, PyObject *);
|
||||
int uwsgi_python_tracer(PyObject *, PyFrameObject *, int, PyObject *);
|
||||
|
||||
void uwsgi_python_reset_random_seed(void);
|
||||
|
||||
char *uwsgi_pythonize(char *);
|
||||
void *uwsgi_python_autoreloader_thread(void *);
|
||||
|
||||
int uwsgi_python_manage_exceptions(void);
|
||||
|
||||
#ifdef UWSGI_PYPY
|
||||
#undef UWSGI_MINTERPRETERS
|
||||
|
||||
@@ -134,9 +134,6 @@ void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyObject *pychunk;
|
||||
ssize_t wsize;
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// ok its a yield
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
@@ -170,11 +167,14 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
Py_DECREF(spit_args);
|
||||
|
||||
if (PyString_Check((PyObject *)wsgi_req->async_placeholder)) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_placeholder), PyString_Size(wsgi_req->async_placeholder))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
goto clear;
|
||||
char *content = PyString_AsString(wsgi_req->async_placeholder);
|
||||
size_t content_len = PyString_Size(wsgi_req->async_placeholder);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -189,7 +189,6 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
#endif
|
||||
@@ -211,32 +210,28 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (PyString_Check(pychunk)) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
char *content = PyString_AsString(pychunk);
|
||||
size_t content_len = PyString_Size(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
Py_DECREF(pychunk);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
}
|
||||
|
||||
|
||||
Py_DECREF(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
|
||||
clear:
|
||||
if (wsgi_req->async_input) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_input);
|
||||
}
|
||||
if (wsgi_req->async_environ) {
|
||||
PyDict_Clear(wsgi_req->async_environ);
|
||||
}
|
||||
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
|
||||
|
||||
Py_DECREF((PyObject *)wsgi_req->async_result);
|
||||
PyErr_Clear();
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -229,7 +229,7 @@ static PyMethodDef uwsgi_Input_methods[] = {
|
||||
|
||||
PyTypeObject uwsgi_InputType = {
|
||||
PyVarObject_HEAD_INIT(NULL, 0)
|
||||
"uwsgi._Input", /*tp_name */
|
||||
"uwsgi._Input", /*tp_name */
|
||||
sizeof(uwsgi_Input), /*tp_basicsize */
|
||||
0, /*tp_itemsize */
|
||||
(destructor) uwsgi_Input_free, /*tp_dealloc */
|
||||
@@ -278,6 +278,12 @@ PyObject *py_uwsgi_write(PyObject * self, PyObject * args) {
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, content, len);
|
||||
UWSGI_GET_GIL
|
||||
// this is a special case for the write callable
|
||||
// no need to honout write-errors-exception-only
|
||||
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) {
|
||||
uwsgi_py_write_set_exception(wsgi_req);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
@@ -363,7 +369,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (wsgi_req->appid_len == 0) {
|
||||
if (!up.ignore_script_name) {
|
||||
if (!uwsgi.ignore_script_name) {
|
||||
wsgi_req->appid = wsgi_req->script_name;
|
||||
wsgi_req->appid_len = wsgi_req->script_name_len;
|
||||
}
|
||||
@@ -445,8 +451,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->async_result = wi->request_subhandler(wsgi_req, wi);
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
if (wsgi_req->async_result) {
|
||||
|
||||
|
||||
@@ -466,7 +470,7 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
}
|
||||
|
||||
else if (up.catch_exceptions) {
|
||||
else if (uwsgi.catch_exceptions) {
|
||||
|
||||
// LOCK THIS PART
|
||||
|
||||
@@ -501,6 +505,16 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
close(tmp_stderr);
|
||||
}
|
||||
|
||||
// this object must be freed/cleared always
|
||||
if (wsgi_req->async_input) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_input);
|
||||
}
|
||||
if (wsgi_req->async_environ) {
|
||||
PyDict_Clear(wsgi_req->async_environ);
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
clear:
|
||||
|
||||
up.reset_ts(wsgi_req, wi);
|
||||
@@ -513,6 +527,24 @@ clear2:
|
||||
|
||||
void uwsgi_after_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (up.after_req_hook) {
|
||||
if (uwsgi.harakiri_no_arh) {
|
||||
// leave harakiri mode
|
||||
if (uwsgi.workers[uwsgi.mywid].harakiri > 0)
|
||||
set_harakiri(0);
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
PyObject *arh = python_call(up.after_req_hook, up.after_req_hook_args, 0, NULL);
|
||||
if (!arh) {
|
||||
PyErr_Print();
|
||||
}
|
||||
else {
|
||||
Py_DECREF(arh);
|
||||
}
|
||||
PyErr_Clear();
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING] || wsgi_req->log_this) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
@@ -599,3 +631,23 @@ void simple_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
PyThreadState_Swap(wi->interpreter);
|
||||
}
|
||||
}
|
||||
|
||||
void simple_threaded_reset_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
|
||||
// restoring main interpreter
|
||||
UWSGI_GET_GIL
|
||||
PyThreadState_Swap(up.main_thread);
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void simple_threaded_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
|
||||
|
||||
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
|
||||
// set the interpreter
|
||||
UWSGI_GET_GIL
|
||||
PyThreadState_Swap(wi->interpreter);
|
||||
UWSGI_RELEASE_GIL
|
||||
}
|
||||
}
|
||||
|
||||
@@ -201,6 +201,11 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
|
||||
UWSGI_GET_GIL
|
||||
#endif
|
||||
|
||||
if (wsgi_req->write_errors > uwsgi.write_errors_tolerance) {
|
||||
uwsgi_py_write_set_exception(wsgi_req);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//uwsgi_log("%d %p\n", wsgi_req->poll.fd, up.wsgi_writeout);
|
||||
Py_INCREF(up.wsgi_writeout);
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
#endif
|
||||
PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
|
||||
Py_DECREF(pydictkey);
|
||||
Py_DECREF(pydictvalue);
|
||||
Py_DECREF(pydictvalue);
|
||||
}
|
||||
|
||||
if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
|
||||
@@ -48,7 +48,6 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
}
|
||||
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
// if async_post is mapped as a file, directly use it as wsgi.input
|
||||
if (wsgi_req->async_post) {
|
||||
#ifdef PYTHREE
|
||||
@@ -69,7 +68,6 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->sendfile);
|
||||
@@ -85,11 +83,9 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", wi->gateway_version);
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
zero = PyFile_FromFile(stderr, "wsgi_errors", "w", NULL);
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.errors", zero);
|
||||
Py_DECREF(zero);
|
||||
#endif
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.run_once", Py_False);
|
||||
|
||||
@@ -108,6 +104,7 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_True);
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->scheme_len > 0) {
|
||||
zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
|
||||
}
|
||||
@@ -125,16 +122,12 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
|
||||
Py_DECREF(zero);
|
||||
|
||||
|
||||
wsgi_req->async_app = wi->callable;
|
||||
|
||||
|
||||
// export .env only in non-threaded mode
|
||||
#ifndef UWSGI_PYPY
|
||||
if (uwsgi.threads < 2) {
|
||||
PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
|
||||
}
|
||||
#endif
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);
|
||||
|
||||
@@ -156,39 +149,29 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
|
||||
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_log("routing %d routes %d\n", uwsgi.routing, uwsgi.nroutes);
|
||||
if (uwsgi.routing && uwsgi.nroutes > 0) {
|
||||
check_route(uwsgi, wsgi_req);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// call
|
||||
|
||||
|
||||
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
|
||||
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions, wsgi_req);
|
||||
return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
|
||||
}
|
||||
|
||||
int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
PyObject *pychunk;
|
||||
ssize_t wsize;
|
||||
#ifdef UWSGI_SENDFILE
|
||||
ssize_t sf_len = 0;
|
||||
#endif
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// return or yield ?
|
||||
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(wsgi_req->async_result), PyString_Size(wsgi_req->async_result))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
goto clear;
|
||||
char *content = PyString_AsString(wsgi_req->async_result);
|
||||
size_t content_len = PyString_Size(wsgi_req->async_result);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -205,7 +188,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
if (wsgi_req->response_size < wsgi_req->sendfile_fd_size) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
}
|
||||
@@ -223,7 +205,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
#ifdef UWSGI_ASYNC
|
||||
if (uwsgi.async > 1) {
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
#endif
|
||||
@@ -234,15 +215,34 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
pychunk = PyIter_Next(wsgi_req->async_placeholder);
|
||||
|
||||
|
||||
if (!pychunk) {
|
||||
if (PyErr_Occurred()) {
|
||||
int do_exit = uwsgi_python_manage_exceptions();
|
||||
if (PyErr_ExceptionMatches(PyExc_MemoryError)) {
|
||||
uwsgi_log("Memory Error detected !!!\n");
|
||||
}
|
||||
uwsgi.workers[uwsgi.mywid].exceptions++;
|
||||
uwsgi_apps[wsgi_req->app_id].exceptions++;
|
||||
PyErr_Print();
|
||||
if (do_exit) {
|
||||
exit(UWSGI_EXCEPTION_CODE);
|
||||
}
|
||||
}
|
||||
if (PyObject_HasAttrString((PyObject *)wsgi_req->async_result, "close")) {
|
||||
PyObject *close_method = PyObject_GetAttrString((PyObject *)wsgi_req->async_result, "close");
|
||||
PyObject *close_method_args = PyTuple_New(0);
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("calling close() for %.*s %p %p\n", wsgi_req->uri_len, wsgi_req->uri, close_method, close_method_args);
|
||||
#endif
|
||||
PyObject *close_method_output = PyEval_CallObject(close_method, close_method_args);
|
||||
if (PyErr_Occurred()) {
|
||||
PyErr_Print();
|
||||
}
|
||||
Py_DECREF(close_method_args);
|
||||
Py_XDECREF(close_method_output);
|
||||
Py_DECREF(close_method);
|
||||
}
|
||||
goto clear;
|
||||
}
|
||||
|
||||
@@ -250,12 +250,16 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
if (PyString_Check(pychunk)) {
|
||||
if ((wsize = wsgi_req->socket->proto_write(wsgi_req, PyString_AsString(pychunk), PyString_Size(pychunk))) < 0) {
|
||||
uwsgi_error("write()");
|
||||
char *content = PyString_AsString(pychunk);
|
||||
size_t content_len = PyString_Size(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
Py_DECREF(pychunk);
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->response_size += wsize;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SENDFILE
|
||||
@@ -268,7 +272,6 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
|
||||
Py_DECREF(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_AGAIN;
|
||||
|
||||
clear:
|
||||
@@ -276,18 +279,11 @@ clear:
|
||||
if (wsgi_req->sendfile_fd != -1) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_sendfile);
|
||||
}
|
||||
if (wsgi_req->async_input) {
|
||||
Py_DECREF((PyObject *)wsgi_req->async_input);
|
||||
}
|
||||
if (wsgi_req->async_environ) {
|
||||
PyDict_Clear(wsgi_req->async_environ);
|
||||
}
|
||||
Py_XDECREF((PyObject *)wsgi_req->async_placeholder);
|
||||
clear2:
|
||||
Py_DECREF((PyObject *)wsgi_req->async_result);
|
||||
PyErr_Clear();
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python24'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.4-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python24_plugin')
|
||||
LDFLAGS = os.popen('python2.4-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python2.4-config --libs').read().rstrip().split()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python25'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.5-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python25_plugin')
|
||||
LDFLAGS = os.popen('python2.5-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python2.5-config --libs').read().rstrip().split()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python26'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.6-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python26_plugin')
|
||||
LDFLAGS = os.popen('python2.6-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python2.6-config --libs').read().rstrip().split()
|
||||
@@ -1,12 +0,0 @@
|
||||
import os,sys
|
||||
|
||||
NAME='python27'
|
||||
|
||||
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
|
||||
|
||||
CFLAGS = os.popen('python2.7-config --cflags').read().rstrip().split()
|
||||
CFLAGS.append('-Wno-unused-parameter')
|
||||
CFLAGS.append('-Wno-strict-prototypes')
|
||||
CFLAGS.append('-Dpython_plugin=python27_plugin')
|
||||
LDFLAGS = os.popen('python2.7-config --ldflags').read().rstrip().split()
|
||||
LIBS = os.popen('python2.7-config --libs').read().rstrip().split()
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user