mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec954b8aa7 | ||
|
|
95d20e9f48 | ||
|
|
165aad8cd0 | ||
|
|
29c339a3c3 | ||
|
|
12afba035b | ||
|
|
eeb203afd4 | ||
|
|
6a18d10c56 | ||
|
|
d1383d7749 | ||
|
|
0abbabbe10 | ||
|
|
ea44525c22 | ||
|
|
2396c7cf31 | ||
|
|
4805a9c219 | ||
|
|
882cdcc2b6 | ||
|
|
59c8bb51b4 | ||
|
|
3c2350f5ad | ||
|
|
422e958fe3 | ||
|
|
4d9c7809d6 | ||
|
|
6b3d8ea146 | ||
|
|
b5d8538fe8 | ||
|
|
47796b315e | ||
|
|
222bcd8fdc | ||
|
|
f92b800a7c | ||
|
|
dec2b234f8 | ||
|
|
3dbd7e3115 | ||
|
|
09d8747918 | ||
|
|
fa78fd915b | ||
|
|
db56141485 | ||
|
|
7685af4652 | ||
|
|
21cb62db6c | ||
|
|
c62aa8e7ed | ||
|
|
4765965d8e | ||
|
|
556feaef2c | ||
|
|
799b8a22e0 | ||
|
|
2336580164 | ||
|
|
ca4f30c003 | ||
|
|
d7d0a71d87 | ||
|
|
44b92f1578 | ||
|
|
abed95362f | ||
|
|
72ecc217f7 | ||
|
|
1405d01d50 | ||
|
|
def65c4793 | ||
|
|
26386909de | ||
|
|
2d4e04059a | ||
|
|
ac557739c2 | ||
|
|
73bfc20ba1 | ||
|
|
6d5ae96d50 | ||
|
|
20b5b7b0dc | ||
|
|
82c5afd0c7 | ||
|
|
ec14f5b0fe | ||
|
|
d93bdcb7b4 | ||
|
|
b68ffc842d | ||
|
|
0326c1d508 | ||
|
|
42f45bfbf9 | ||
|
|
d018d3af99 | ||
|
|
42afc476d7 | ||
|
|
b5037d3f0f | ||
|
|
065dd7cfff | ||
|
|
7909e092b5 | ||
|
|
9da53f5fd4 | ||
|
|
025cb7744e | ||
|
|
e48a3ff1b7 | ||
|
|
2be371003c | ||
|
|
60d940e301 | ||
|
|
96c56cd8d5 | ||
|
|
4184619f7b | ||
|
|
50a8ec8a19 | ||
|
|
79c702278a | ||
|
|
8fc41a4c85 | ||
|
|
9c6455252d | ||
|
|
83e41844f3 | ||
|
|
2cc17d6b11 | ||
|
|
14057b72c8 | ||
|
|
faf72b6a77 | ||
|
|
963afa5174 | ||
|
|
ce8ff8c45f | ||
|
|
5ae742e8e1 | ||
|
|
60f6572985 | ||
|
|
4ea34c63d2 | ||
|
|
5699d21aa7 | ||
|
|
dda8d25495 | ||
|
|
d4f690322c | ||
|
|
4f2f30d1e5 | ||
|
|
d3b28e7956 | ||
|
|
ab4afdbeaa | ||
|
|
54e2d698cb | ||
|
|
8b0565c0b8 | ||
|
|
102d6f25ed | ||
|
|
d0a53aa976 | ||
|
|
f8cf808e47 | ||
|
|
f8bbd2177e | ||
|
|
f44c145941 | ||
|
|
f34ac9f6aa | ||
|
|
b971230fd9 | ||
|
|
5c6340caac | ||
|
|
c0b97b47d3 | ||
|
|
a6b7f6e5bb | ||
|
|
1b99f9a750 | ||
|
|
a434195318 | ||
|
|
a6a8faea78 | ||
|
|
31458320ab | ||
|
|
037a1f7f77 | ||
|
|
10d4d10ac9 | ||
|
|
00e8d509f8 | ||
|
|
c9ca14df4d | ||
|
|
841cdfc62d | ||
|
|
fc7026c076 | ||
|
|
b96581c183 | ||
|
|
4fa5d72af6 | ||
|
|
f4be581666 | ||
|
|
24fb5518d8 | ||
|
|
2e8061d62a | ||
|
|
23d70f6936 | ||
|
|
95ea88628a | ||
|
|
68b411f487 | ||
|
|
40bfbc0a44 | ||
|
|
fc9b6ea275 | ||
|
|
522f3bb3a1 | ||
|
|
743c7ceaa6 | ||
|
|
c780cd47ce | ||
|
|
54e7e01c05 | ||
|
|
7d422d11e4 | ||
|
|
5c35b60d1d | ||
|
|
94353efb3f | ||
|
|
0586a2ba47 | ||
|
|
be6081c6f7 | ||
|
|
955fb6479e | ||
|
|
1b334e8cf7 | ||
|
|
718e198ac8 | ||
|
|
3757e5a8bb | ||
|
|
d505964321 | ||
|
|
1114c1a429 | ||
|
|
f58a9c6119 | ||
|
|
e791cb2c00 | ||
|
|
f741dbb01b | ||
|
|
d5f0741e8d | ||
|
|
b265ed8313 | ||
|
|
6cb160bb26 | ||
|
|
009a3f2c0d | ||
|
|
11b3d1fb94 | ||
|
|
7a39472700 | ||
|
|
4489b48603 | ||
|
|
d2f69af964 | ||
|
|
34e9dabffc | ||
|
|
6a4f46639e | ||
|
|
0d07ff25f9 | ||
|
|
c1d9c4ef12 | ||
|
|
0227ff7a9b | ||
|
|
082b178ae3 | ||
|
|
0e695cbd6e | ||
|
|
be2ed4dc4a | ||
|
|
4777666588 | ||
|
|
5647057ecc | ||
|
|
94cb950058 | ||
|
|
8d65371bf6 | ||
|
|
c747a36ae1 | ||
|
|
e51cb65857 | ||
|
|
8fa4fdb8c8 | ||
|
|
d584857c78 | ||
|
|
f0b1d79f8b | ||
|
|
28566ad772 | ||
|
|
40c0e139d4 | ||
|
|
04f2444ea0 | ||
|
|
9f71d28afa | ||
|
|
af262fb325 | ||
|
|
243657b5aa | ||
|
|
032302edaa | ||
|
|
d4bd658d84 | ||
|
|
78843c3e06 | ||
|
|
692ba1f6b3 | ||
|
|
400a9d72ef | ||
|
|
11f8f0385a | ||
|
|
c40d15981c | ||
|
|
baa1bf21f1 | ||
|
|
3dd3122236 | ||
|
|
927ef2ccde | ||
|
|
af6eaf6737 | ||
|
|
7c543f5627 | ||
|
|
b06e35c610 | ||
|
|
842c2148d7 | ||
|
|
a2a94bd78e | ||
|
|
4452c30fc8 | ||
|
|
f462792c8e | ||
|
|
03879fdc0c | ||
|
|
389d0b95d5 | ||
|
|
6ec32e192f | ||
|
|
22c034cdca | ||
|
|
396d8c3022 | ||
|
|
a535ecbe17 | ||
|
|
fd436c3e4f | ||
|
|
e5c245ea2f | ||
|
|
3008b7c83b | ||
|
|
eca6cd3066 | ||
|
|
691a41f290 | ||
|
|
df4cf539a1 | ||
|
|
baa1167dfe | ||
|
|
d8a83ab7cf | ||
|
|
8184351b3b | ||
|
|
4a4dbbcf69 | ||
|
|
56f79efc74 | ||
|
|
ea073a9bbd | ||
|
|
c5b2ca4b20 | ||
|
|
c0f9d8d2ff | ||
|
|
497660279f | ||
|
|
625395bd26 | ||
|
|
79a7797409 | ||
|
|
3b13de3e6e | ||
|
|
7f99855527 | ||
|
|
8c29178f81 | ||
|
|
ed71000033 | ||
|
|
20860ed069 | ||
|
|
2e62f13917 | ||
|
|
1b2a83ce70 | ||
|
|
113ec5ae9e | ||
|
|
68e81828d1 | ||
|
|
543790dc83 | ||
|
|
be24060578 | ||
|
|
bdedc1c94c | ||
|
|
e2454aa898 | ||
|
|
dfa4834be3 | ||
|
|
f204249110 | ||
|
|
f4c25a6cd1 | ||
|
|
fbfbacce14 | ||
|
|
a0eed32b3f | ||
|
|
9fe9fe1bb6 | ||
|
|
192312e3ea | ||
|
|
ee46fe6ba6 | ||
|
|
58abd07a88 | ||
|
|
c246a6008e | ||
|
|
706f1b59c3 | ||
|
|
ddbc8920f7 | ||
|
|
7e3bf6868e | ||
|
|
4c7ecef577 | ||
|
|
e3da0aaad4 | ||
|
|
99e576e40c | ||
|
|
7604ce3441 | ||
|
|
a0082b5b98 | ||
|
|
c90c639348 | ||
|
|
2e188dc25a | ||
|
|
312d21cb3f | ||
|
|
4ee138be7c | ||
|
|
299aef99b3 | ||
|
|
06953e4547 | ||
|
|
7565ee8740 | ||
|
|
10377f02a3 | ||
|
|
a41e6e2c61 | ||
|
|
6b2b909d33 | ||
|
|
70cd18bffb | ||
|
|
d6be4bcad9 | ||
|
|
85530b5d8e | ||
|
|
e3848e84d3 | ||
|
|
4ec9312b10 | ||
|
|
aedf3b2455 | ||
|
|
2210ec7f71 | ||
|
|
a9bee41707 | ||
|
|
3adbfd100f | ||
|
|
8d8de4b8da | ||
|
|
099403d554 | ||
|
|
13938a6aa7 | ||
|
|
9be3a4aaf8 | ||
|
|
009e42f349 | ||
|
|
207dd3bc77 | ||
|
|
feec6b3151 | ||
|
|
bf8207f0f1 | ||
|
|
9fcbc6ee68 | ||
|
|
dcb58aaa34 | ||
|
|
7163d8ddd4 | ||
|
|
c7b24eec45 | ||
|
|
1e7098f787 | ||
|
|
b28f0d9863 | ||
|
|
b49c4f4af9 | ||
|
|
2c39aafb0b | ||
|
|
1036d9c18b | ||
|
|
f0c8cbf190 | ||
|
|
f51db4481b | ||
|
|
717eba7ab3 | ||
|
|
3cc971ba55 | ||
|
|
23b3d7483f | ||
|
|
ba03837e29 | ||
|
|
06952fbaff | ||
|
|
27be00b4cc | ||
|
|
b50a377190 | ||
|
|
1ed9cb0bec | ||
|
|
a548ede3c7 | ||
|
|
de26c09030 | ||
|
|
19aa7c2560 | ||
|
|
215e0c4cbc | ||
|
|
d484acefa4 | ||
|
|
4032efd3e8 | ||
|
|
f9d412bcca | ||
|
|
5f52063b9e | ||
|
|
87833abb42 | ||
|
|
0fcbd5e334 | ||
|
|
5b55bf5f5c | ||
|
|
b8cc1d962f | ||
|
|
762c73e2ac | ||
|
|
57cd0e9135 | ||
|
|
5e0a85bff0 | ||
|
|
d2eaef524c | ||
|
|
a98c5a3931 | ||
|
|
040da07323 | ||
|
|
34f43ec97b | ||
|
|
7e3cfe94d6 | ||
|
|
e2c3b650a1 | ||
|
|
404dfaeda7 | ||
|
|
a1ec530945 | ||
|
|
b8dfd617f2 | ||
|
|
f34ed4dc47 | ||
|
|
cd2ff0e585 | ||
|
|
449955562f | ||
|
|
41a4bbccfc | ||
|
|
87b17c001d | ||
|
|
67b7753814 | ||
|
|
b190744b77 | ||
|
|
4b603071d8 | ||
|
|
16c55f0217 | ||
|
|
c989f2fb33 | ||
|
|
6429a47b0d | ||
|
|
f8a48a3ae9 | ||
|
|
fb3272d165 | ||
|
|
be5f67906e | ||
|
|
f730023e88 | ||
|
|
edbff83fd6 |
@@ -1,3 +1,19 @@
|
||||
----------------------------------------------------------------------
|
||||
|
||||
LINKING EXCEPTION
|
||||
|
||||
In addition to the permissions in the GNU General Public License,
|
||||
the authors give you unlimited permission to link the compiled
|
||||
version of this library into combinations with other programs,
|
||||
and to distribute those combinations without any restriction
|
||||
coming from the use of this file. (The General Public License
|
||||
restrictions do apply in other respects; for example, they cover
|
||||
modification of the file, and distribution when not linked into
|
||||
a combined executable.)
|
||||
|
||||
----------------------------------------------------------------------
|
||||
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
|
||||
@@ -1,8 +1,16 @@
|
||||
PYTHON := python
|
||||
|
||||
all:
|
||||
python uwsgiconfig.py --build
|
||||
$(PYTHON) uwsgiconfig.py --build $(PROFILE)
|
||||
|
||||
clean:
|
||||
python uwsgiconfig.py --clean
|
||||
$(PYTHON) uwsgiconfig.py --clean
|
||||
|
||||
check:
|
||||
python uwsgiconfig.py --check
|
||||
$(PYTHON) uwsgiconfig.py --check
|
||||
|
||||
plugin.%:
|
||||
$(PYTHON) uwsgiconfig.py --plugin plugins/$* $(PROFILE)
|
||||
|
||||
%:
|
||||
$(PYTHON) uwsgiconfig.py --build $@
|
||||
|
||||
@@ -7,7 +7,7 @@ filename = sys.argv[1]
|
||||
size = os.path.getsize(filename)
|
||||
|
||||
f = open(filename, 'r')
|
||||
print(f.read())
|
||||
os.write(1, f.read())
|
||||
f.close()
|
||||
|
||||
print(struct.pack("<Q", size))
|
||||
os.write(1, (struct.pack("<Q", size)))
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados
|
||||
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados,pypy
|
||||
inherit = base
|
||||
|
||||
+1
-2
@@ -6,7 +6,6 @@ zeromq = auto
|
||||
ssl = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
matheval = auto
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
@@ -17,7 +16,7 @@ plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires
|
||||
embedded_plugins = %(main_plugin)s, ping, cache, nagios, rrdtool, carbon, rpc, corerouter, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool, redislog, mongodblog, router_rewrite, router_http, logfile, router_cache, rawrouter, router_static, sslrouter, spooler, cheaper_busyness, symcall, transformation_tofile, transformation_gzip, transformation_chunked, transformation_offload, router_memcached, router_redis, router_hash, router_expires, router_metrics, transformation_template, stats_pusher_socket
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
[uwsgi]
|
||||
# pypy,jvm,ring,jwsgi
|
||||
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
|
||||
main_plugin = psgi,rack,lua,python,gevent,php,cgi,glusterfs,pty,xslt,msgpack,geoip,v8,pam,ldap,mono,jvm,ring,jwsgi,servlet,rados,coroae,pypy,gccgo
|
||||
inherit = base
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = gccgo
|
||||
inherit = base
|
||||
@@ -1,4 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = glusterfs
|
||||
inherit = base
|
||||
matheval = false
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
[uwsgi]
|
||||
main_plugin = go
|
||||
inherit = base
|
||||
bin_name = libuwsgi.so
|
||||
as_shared_library = true
|
||||
@@ -0,0 +1,32 @@
|
||||
[uwsgi]
|
||||
xml = false
|
||||
yaml = false
|
||||
json = false
|
||||
zeromq = false
|
||||
ssl = false
|
||||
pcre = false
|
||||
routing = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = none
|
||||
yaml_implementation = none
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = uwsgi
|
||||
append_version =
|
||||
plugin_dir = .
|
||||
embedded_plugins = %(main_plugin)s
|
||||
as_shared_library = false
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = psgi
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = python
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = pypy
|
||||
inherit = minimal
|
||||
@@ -0,0 +1,3 @@
|
||||
[uwsgi]
|
||||
main_plugin = rack
|
||||
inherit = minimal
|
||||
+27
-22
@@ -4,18 +4,18 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is a general purpose async loop engine (it expects a coroutine based approach)
|
||||
This is a general-purpose async loop engine (it expects a coroutine-based approach)
|
||||
|
||||
You can see it as an hub holding the following structures:
|
||||
|
||||
1) the runqueue, cores ready to be run are appended in this list
|
||||
1) the runqueue, cores ready to be run are appended to this list
|
||||
|
||||
2) the fd list, this is a list of monitored file descriptors, a core can wait for all the file descriptors it needs
|
||||
|
||||
3) the timeout value, if set the current core will timeout aftert he specified number of seconds (unless an event cancel it)
|
||||
3) the timeout value, if set, the current core will timeout after the specified number of seconds (unless an event cancels it)
|
||||
|
||||
|
||||
IMPORTANT: this is not a callback based engine !!!
|
||||
IMPORTANT: this is not a callback-based engine !!!
|
||||
|
||||
*/
|
||||
|
||||
@@ -159,7 +159,7 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
// timeout expired
|
||||
wsgi_req->async_timed_out = 1;
|
||||
// reset teh request
|
||||
// reset the request
|
||||
async_reset_request(wsgi_req);
|
||||
// push it in the runqueue
|
||||
runqueue_push(wsgi_req);
|
||||
@@ -308,29 +308,42 @@ end:
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
}
|
||||
|
||||
void async_schedule_to_req_green(void) {
|
||||
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
for(;;) {
|
||||
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
uwsgi.wsgi_req->switches++;
|
||||
wsgi_req->switches++;
|
||||
if (uwsgi.schedule_fix) {
|
||||
uwsgi.schedule_fix(wsgi_req);
|
||||
}
|
||||
// switch after each yield
|
||||
uwsgi.schedule_to_main(uwsgi.wsgi_req);
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
end:
|
||||
#endif
|
||||
async_reset_request(uwsgi.wsgi_req);
|
||||
uwsgi_close_request(uwsgi.wsgi_req);
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
// re-set the global state
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
async_reset_request(wsgi_req);
|
||||
uwsgi_close_request(wsgi_req);
|
||||
// re-set the global state (routing could have changed it)
|
||||
uwsgi.wsgi_req = wsgi_req;
|
||||
wsgi_req->async_status = UWSGI_OK;
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req;
|
||||
|
||||
}
|
||||
|
||||
void async_loop() {
|
||||
@@ -511,19 +524,11 @@ void async_loop() {
|
||||
uwsgi.wsgi_req->switches++;
|
||||
|
||||
// request ended ?
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK ||
|
||||
uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
|
||||
// remove from the runqueue
|
||||
runqueue_remove(current_request);
|
||||
// push wsgi_request in the unused stack
|
||||
uwsgi.async_queue_unused_ptr++;
|
||||
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
|
||||
|
||||
}
|
||||
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
|
||||
// remove this request from the runqueue
|
||||
runqueue_remove(current_request);
|
||||
}
|
||||
|
||||
current_request = next_request;
|
||||
}
|
||||
|
||||
|
||||
@@ -204,6 +204,19 @@ int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
int uwsgi_buffer_u64le(struct uwsgi_buffer *ub, uint64_t num) {
|
||||
uint8_t buf[8];
|
||||
buf[0] = (uint8_t) (num & 0xff);
|
||||
buf[1] = (uint8_t) ((num >> 8) & 0xff);
|
||||
buf[2] = (uint8_t) ((num >> 16) & 0xff);
|
||||
buf[3] = (uint8_t) ((num >> 24) & 0xff);
|
||||
buf[4] = (uint8_t) ((num >> 32) & 0xff);
|
||||
buf[5] = (uint8_t) ((num >> 40) & 0xff);
|
||||
buf[6] = (uint8_t) ((num >> 48) & 0xff);
|
||||
buf[7] = (uint8_t) ((num >> 56) & 0xff);
|
||||
return uwsgi_buffer_append(ub, (char *) buf, 8);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_buffer_f64be(struct uwsgi_buffer *ub, double num) {
|
||||
uint8_t buf[8];
|
||||
|
||||
+7
-7
@@ -7,7 +7,7 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
/* how the cache bitmap works:
|
||||
|
||||
a bitmap is a shared mempry area allocated when requested by the user with --cache2
|
||||
a bitmap is a shared memory area allocated when requested by the user with --cache2
|
||||
|
||||
Each block maps to a bit in the bitmap. If the corresponding bit is cleared
|
||||
the block is usable otherwise the block scanner will search for the next one.
|
||||
@@ -325,7 +325,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
exit(1);
|
||||
}
|
||||
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
|
||||
if (!uc->items) {
|
||||
if (uc->items == MAP_FAILED) {
|
||||
uwsgi_error("uwsgi_cache_init()/mmap() [with store]");
|
||||
exit(1);
|
||||
}
|
||||
@@ -335,7 +335,7 @@ void uwsgi_cache_init(struct uwsgi_cache *uc) {
|
||||
}
|
||||
else {
|
||||
uc->items = (struct uwsgi_cache_item *) mmap(NULL, uc->filesize, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
if (!uc->items) {
|
||||
if (uc->items == MAP_FAILED) {
|
||||
uwsgi_error("uwsgi_cache_init()/mmap()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -762,7 +762,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize teh scan
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
@@ -773,7 +773,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
cache_unmark_blocks(uc, uci->first_block, uci->valsize);
|
||||
}
|
||||
if ( !(flags & UWSGI_CACHE_FLAG_MATH)) {
|
||||
memcpy(uc->data + (uci->first_block * uc->blocksize), val, vallen);
|
||||
memcpy(((char *) uc->data) + (uci->first_block * uc->blocksize), val, vallen);
|
||||
}
|
||||
else {
|
||||
int64_t *num = (int64_t *)(((char *) uc->data) + (uci->first_block * uc->blocksize));
|
||||
@@ -1432,7 +1432,7 @@ static int cache_magic_send_and_manage(int fd, struct uwsgi_buffer *ub, char *st
|
||||
// ok now wait for the response, using the same buffer of the request
|
||||
// NOTE: after using a uwsgi_buffer in that way we basically destroy (even if we can safely free it)
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout)) return -1;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, timeout, NULL, NULL)) return -1;
|
||||
// try to fix the buffer to maintain size info
|
||||
ub->pos = rlen;
|
||||
|
||||
@@ -1867,7 +1867,7 @@ void uwsgi_cache_sync_from_nodes(struct uwsgi_cache *uc) {
|
||||
}
|
||||
|
||||
size_t rlen = ub->pos;
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
if (uwsgi_read_with_realloc(fd, &ub->buf, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL, NULL)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_log("[cache-sync] unable to read from the cache server\n");
|
||||
close(fd);
|
||||
|
||||
+327
-6
@@ -293,8 +293,25 @@ int uwsgi_count_options(struct uwsgi_option *uopt) {
|
||||
return count;
|
||||
}
|
||||
|
||||
int uwsgi_opt_exists(char *name) {
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
while (op->name) {
|
||||
if (!strcmp(name, op->name)) return 1;
|
||||
op++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
avoid loops here !!!
|
||||
*/
|
||||
struct uwsgi_option *uwsgi_opt_get(char *name) {
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
struct uwsgi_option *op;
|
||||
int round = 0;
|
||||
retry:
|
||||
round++;
|
||||
if (round > 2) goto end;
|
||||
op = uwsgi.options;
|
||||
|
||||
while (op->name) {
|
||||
if (!strcmp(name, op->name)) {
|
||||
@@ -303,10 +320,26 @@ struct uwsgi_option *uwsgi_opt_get(char *name) {
|
||||
op++;
|
||||
}
|
||||
|
||||
if (uwsgi.autoload) {
|
||||
if (uwsgi_try_autoload(name)) goto retry;
|
||||
}
|
||||
|
||||
end:
|
||||
if (uwsgi.strict) {
|
||||
uwsgi_log("[strict-mode] unknown config directive: %s\n", name);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void add_exported_option(char *key, char *value, int configured) {
|
||||
add_exported_option_do(key, value, configured, 0);
|
||||
}
|
||||
|
||||
void add_exported_option_do(char *key, char *value, int configured, int placeholder_only) {
|
||||
|
||||
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
|
||||
struct uwsgi_string_list *whitelist = uwsgi.whitelist;
|
||||
@@ -394,6 +427,15 @@ add:
|
||||
uwsgi.exported_opts_cnt++;
|
||||
uwsgi.dirty_config = 1;
|
||||
|
||||
if (placeholder_only) {
|
||||
if (uwsgi_opt_exists(key)) {
|
||||
uwsgi_log("you cannot use %s as a placeholder, it is already available as an option\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.exported_opts[id]->configured = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
struct uwsgi_option *op = uwsgi_opt_get(key);
|
||||
if (op) {
|
||||
// requires master ?
|
||||
@@ -451,17 +493,16 @@ add:
|
||||
if (op->flags & UWSGI_OPT_MIME) {
|
||||
uwsgi.build_mime_dict = 1;
|
||||
}
|
||||
// enable metrics ?
|
||||
if (op->flags & UWSGI_OPT_METRICS) {
|
||||
uwsgi.has_metrics = 1;
|
||||
}
|
||||
// immediate ?
|
||||
if (op->flags & UWSGI_OPT_IMMEDIATE) {
|
||||
op->func(key, value, op->data);
|
||||
uwsgi.exported_opts[id]->configured = 1;
|
||||
}
|
||||
}
|
||||
else if (uwsgi.strict) {
|
||||
uwsgi_log("[strict-mode] unknown config directive: %s\n", key);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_fallback_config() {
|
||||
@@ -477,3 +518,283 @@ void uwsgi_fallback_config() {
|
||||
// never here
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_manage_opt(char *key, char *value) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi_opt_get(key);
|
||||
if (op) {
|
||||
op->func(key, value, op->data);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_configure() {
|
||||
|
||||
int i;
|
||||
|
||||
// and now apply the remaining configs
|
||||
restart:
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
if (uwsgi.exported_opts[i]->configured)
|
||||
continue;
|
||||
uwsgi.dirty_config = 0;
|
||||
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
|
||||
// some option could cause a dirty config tree
|
||||
if (uwsgi.dirty_config)
|
||||
goto restart;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_custom(char *key, char *value, void *data ) {
|
||||
struct uwsgi_custom_option *uco = (struct uwsgi_custom_option *)data;
|
||||
size_t i, count = 1;
|
||||
size_t value_len = 0;
|
||||
if (value)
|
||||
value_len = strlen(value);
|
||||
off_t pos = 0;
|
||||
char **opt_argv;
|
||||
char *tmp_val = NULL, *p = NULL;
|
||||
|
||||
// now count the number of args
|
||||
for (i = 0; i < value_len; i++) {
|
||||
if (value[i] == ' ') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate a tmp array
|
||||
opt_argv = uwsgi_calloc(sizeof(char *) * count);
|
||||
//make a copy of the value;
|
||||
if (value_len > 0) {
|
||||
tmp_val = uwsgi_str(value);
|
||||
// fill the array of options
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_val, " ", p, ctx) {
|
||||
opt_argv[pos] = p;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no argument specified
|
||||
opt_argv[0] = "";
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found custom option %s with %d args\n", key, count);
|
||||
#endif
|
||||
|
||||
// now make a copy of the option template
|
||||
char *tmp_opt = uwsgi_str(uco->value);
|
||||
// split it
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_opt, ";", p, ctx) {
|
||||
char *equal = strchr(p, '=');
|
||||
if (!equal)
|
||||
goto clear;
|
||||
*equal = '\0';
|
||||
|
||||
// build the key
|
||||
char *new_key = uwsgi_str(p);
|
||||
for (i = 0; i < count; i++) {
|
||||
char *old_key = new_key;
|
||||
char *tmp_num = uwsgi_num2str(i + 1);
|
||||
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
|
||||
free(tmp_num);
|
||||
new_key = uwsgi_substitute(old_key, placeholder, opt_argv[i]);
|
||||
if (new_key != old_key)
|
||||
free(old_key);
|
||||
free(placeholder);
|
||||
}
|
||||
|
||||
// build the value
|
||||
char *new_value = uwsgi_str(equal + 1);
|
||||
for (i = 0; i < count; i++) {
|
||||
char *old_value = new_value;
|
||||
char *tmp_num = uwsgi_num2str(i + 1);
|
||||
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
|
||||
free(tmp_num);
|
||||
new_value = uwsgi_substitute(old_value, placeholder, opt_argv[i]);
|
||||
if (new_value != old_value)
|
||||
free(old_value);
|
||||
free(placeholder);
|
||||
}
|
||||
// ignore return value here
|
||||
uwsgi_manage_opt(new_key, new_value);
|
||||
}
|
||||
|
||||
clear:
|
||||
free(tmp_val);
|
||||
free(tmp_opt);
|
||||
free(opt_argv);
|
||||
|
||||
}
|
||||
|
||||
char *uwsgi_get_exported_opt(char *key) {
|
||||
|
||||
int i;
|
||||
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
if (!strcmp(uwsgi.exported_opts[i]->key, key)) {
|
||||
return uwsgi.exported_opts[i]->value;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *uwsgi_get_optname_by_index(int index) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
|
||||
while (op->name) {
|
||||
if (op->shortcut == index) {
|
||||
return op->name;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
this works as a pipeline
|
||||
|
||||
processes = 2
|
||||
cpu_cores = 8
|
||||
foobar = %(processes cpu_cores + 2)
|
||||
|
||||
translate as:
|
||||
|
||||
step1 = proceses cpu_cores = 2 8 = 28 (string concatenation)
|
||||
|
||||
step1 + = step1_apply_func_plus (func token)
|
||||
|
||||
step1_apply_func_plus 2 = 28 + 2 = 30 (math)
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_manage_placeholder(char *key) {
|
||||
enum {
|
||||
concat = 0,
|
||||
sum,
|
||||
sub,
|
||||
mul,
|
||||
div,
|
||||
} state;
|
||||
|
||||
state = concat;
|
||||
char *current_value = NULL;
|
||||
|
||||
char *space = strchr(key, ' ');
|
||||
if (!space) {
|
||||
return uwsgi_get_exported_opt(key);
|
||||
}
|
||||
// let's start the heavy metal here
|
||||
char *tmp_value = uwsgi_str(key);
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_value, " ", p, ctx) {
|
||||
char *value = NULL;
|
||||
if (is_a_number(p)) {
|
||||
value = uwsgi_str(p);
|
||||
}
|
||||
else if (!strcmp(p, "+")) {
|
||||
state = sum;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "-")) {
|
||||
state = sub;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "*")) {
|
||||
state = mul;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "/")) {
|
||||
state = div;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "++")) {
|
||||
if (current_value) {
|
||||
int64_t tmp_value = strtoll(current_value, NULL, 10);
|
||||
free(current_value);
|
||||
current_value = uwsgi_64bit2str(tmp_value+1);
|
||||
}
|
||||
state = concat;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "--")) {
|
||||
if (current_value) {
|
||||
int64_t tmp_value = strtoll(current_value, NULL, 10);
|
||||
free(current_value);
|
||||
current_value = uwsgi_64bit2str(tmp_value-1);
|
||||
}
|
||||
state = concat;
|
||||
continue;
|
||||
}
|
||||
// find the option
|
||||
else {
|
||||
char *ov = uwsgi_get_exported_opt(p);
|
||||
if (!ov) ov = "";
|
||||
value = uwsgi_str(ov);
|
||||
}
|
||||
|
||||
int64_t arg1n = 0, arg2n = 0;
|
||||
char *arg1 = "", *arg2 = "";
|
||||
|
||||
switch(state) {
|
||||
case concat:
|
||||
if (current_value) arg1 = current_value;
|
||||
if (value) arg2 = value;
|
||||
char *ret = uwsgi_concat2(arg1, arg2);
|
||||
if (current_value) free(current_value);
|
||||
current_value = ret;
|
||||
break;
|
||||
case sum:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
current_value = uwsgi_64bit2str(arg1n + arg2n);
|
||||
break;
|
||||
case sub:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
current_value = uwsgi_64bit2str(arg1n - arg2n);
|
||||
break;
|
||||
case mul:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
current_value = uwsgi_64bit2str(arg1n * arg2n);
|
||||
break;
|
||||
case div:
|
||||
if (current_value) arg1n = strtoll(current_value, NULL, 10);
|
||||
if (value) arg2n = strtoll(value, NULL, 10);
|
||||
if (current_value) free(current_value);
|
||||
// avoid division by zero
|
||||
if (arg2n == 0) {
|
||||
current_value = uwsgi_64bit2str(0);
|
||||
}
|
||||
else {
|
||||
current_value = uwsgi_64bit2str(arg1n / arg2n);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// over engineering
|
||||
if (value)
|
||||
free(value);
|
||||
|
||||
// reset state to concat
|
||||
state = concat;
|
||||
}
|
||||
|
||||
return current_value;
|
||||
}
|
||||
|
||||
+16
-16
@@ -139,6 +139,10 @@ int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
|
||||
}
|
||||
#endif
|
||||
if (ud->pid == diedpid && !ud->pidfile) {
|
||||
if (ud->control) {
|
||||
gracefully_kill_them_all(0);
|
||||
return 0;
|
||||
}
|
||||
uwsgi_spawn_daemon(ud);
|
||||
return 1;
|
||||
}
|
||||
@@ -229,13 +233,15 @@ void uwsgi_detach_daemons() {
|
||||
#endif
|
||||
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
// try to gracefully stop daemon, kill it if it won't die
|
||||
// if mercy is not set than wait up to 3 seconds
|
||||
// if mercy is not set then wait up to 3 seconds
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
int waitpid_status;
|
||||
while (!kill(ud->pid, 0)) {
|
||||
kill(-ud->pid, SIGTERM);
|
||||
sleep(1);
|
||||
waitpid(-ud->pid, &waitpid_status, WNOHANG);
|
||||
if (uwsgi_now() >= timeout) {
|
||||
uwsgi_log("[uwsgi-daemons] daemon did not died in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
kill(-ud->pid, SIGKILL);
|
||||
break;
|
||||
}
|
||||
@@ -253,11 +259,12 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
// skip unregistered daemons
|
||||
if (!ud->registered) return;
|
||||
|
||||
int devnull = -1;
|
||||
int throttle = 0;
|
||||
|
||||
if (uwsgi.current_time - ud->last_spawn <= 3) {
|
||||
throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
|
||||
// if ud->respawns == 0 then we can end up with throttle < 0
|
||||
if (throttle <= 0) throttle = 1;
|
||||
}
|
||||
|
||||
pid_t pid = uwsgi_fork("uWSGI external daemon");
|
||||
@@ -299,18 +306,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
if (!uwsgi.daemons_honour_stdin) {
|
||||
// /dev/null will became stdin
|
||||
devnull = open("/dev/null", O_RDONLY);
|
||||
if (devnull < 0) {
|
||||
uwsgi_error("/dev/null open()");
|
||||
exit(1);
|
||||
}
|
||||
if (devnull != 0) {
|
||||
if (dup2(devnull, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(devnull);
|
||||
}
|
||||
uwsgi_remap_fd(0, "/dev/null");
|
||||
}
|
||||
|
||||
if (setsid() < 0) {
|
||||
@@ -329,7 +325,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
|
||||
|
||||
if (throttle) {
|
||||
uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
|
||||
sleep(throttle);
|
||||
sleep((unsigned int) throttle);
|
||||
}
|
||||
|
||||
uwsgi_log("[uwsgi-daemons] %sspawning \"%s\"\n", ud->respawns > 0 ? "re" : "", ud->command);
|
||||
@@ -412,6 +408,10 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
|
||||
uwsgi_ud->last_spawn = 0;
|
||||
uwsgi_ud->daemonize = daemonize;
|
||||
uwsgi_ud->pidfile = pidfile;
|
||||
uwsgi_ud->control = 0;
|
||||
if (!strcmp(opt, "attach-control-daemon")) {
|
||||
uwsgi_ud->control = 1;
|
||||
}
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_ud->legion = legion;
|
||||
#endif
|
||||
|
||||
+264
-60
@@ -339,8 +339,13 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
struct stat st;
|
||||
struct uwsgi_instance *ui_current;
|
||||
|
||||
if (chdir(uwsgi.cwd)) {
|
||||
uwsgi_error("uwsgi_imperial_monitor_glob()/chdir()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (glob(ues->arg, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
|
||||
uwsgi_error("glob()");
|
||||
uwsgi_error("uwsgi_imperial_monitor_glob()/glob()");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -617,6 +622,7 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
}
|
||||
|
||||
void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
if (c_ui->status == 1) return;
|
||||
// remove uWSGI instance
|
||||
|
||||
if (write(c_ui->pipe[0], "\0", 1) != 1) {
|
||||
@@ -624,10 +630,23 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
}
|
||||
|
||||
c_ui->status = 1;
|
||||
c_ui->cursed_at = uwsgi_now();
|
||||
|
||||
uwsgi_log("[emperor] stop the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_curse(struct uwsgi_instance *c_ui) {
|
||||
if (c_ui->status == 1) return;
|
||||
// curse uWSGI instance
|
||||
|
||||
c_ui->status = 1;
|
||||
c_ui->cursed_at = uwsgi_now();
|
||||
|
||||
uwsgi_log("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
|
||||
struct uwsgi_header uh;
|
||||
@@ -817,7 +836,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
// TODO pre-start hook
|
||||
|
||||
// a new uWSGI instance will start
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
|
||||
if (uwsgi.emperor_clone) {
|
||||
char stack[PTHREAD_STACK_MIN];
|
||||
pid = clone((int (*)(void *))uwsgi_emperor_spawn_vassal, stack + PTHREAD_STACK_MIN, SIGCHLD | uwsgi.emperor_clone, (void *) n_ui);
|
||||
@@ -825,7 +844,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
else {
|
||||
#endif
|
||||
pid = fork();
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
|
||||
}
|
||||
#endif
|
||||
if (pid < 0) {
|
||||
@@ -940,6 +959,61 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
|
||||
static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
|
||||
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
|
||||
uwsgi_error("prctl()");
|
||||
}
|
||||
#ifdef CLONE_NEWUSER
|
||||
if (uwsgi.emperor_clone & CLONE_NEWUSER) {
|
||||
if (setuid(0)) {
|
||||
uwsgi_error("uwsgi_emperor_spawn_vassal()/setuid(0)");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
#if defined(CAP_LAST_CAP) && defined(PR_CAPBSET_READ) && defined(PR_CAPBSET_DROP)
|
||||
if (uwsgi.emperor_cap && uwsgi.emperor_cap_count > 0) {
|
||||
int i;
|
||||
for(i=0;i<=CAP_LAST_CAP;i++) {
|
||||
|
||||
int has_cap = prctl(PR_CAPBSET_READ, i, 0, 0, 0);
|
||||
if (has_cap == 1) {
|
||||
if (i == CAP_SETPCAP) continue;
|
||||
int j;int found = 0;
|
||||
for(j=0;j<uwsgi.emperor_cap_count;j++) {
|
||||
if (uwsgi.emperor_cap[j] == (int) i) {
|
||||
found = 1; break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
if (prctl(PR_CAPBSET_DROP, i, 0, 0, 0)) {
|
||||
uwsgi_error("uwsgi_emperor_spawn_vassal()/prctl()");
|
||||
uwsgi_log_verbose("unable to drop capability %lu\n", i);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
// just for being paranoid
|
||||
#ifdef SECBIT_KEEP_CAPS
|
||||
if (prctl(SECBIT_KEEP_CAPS, 1, 0, 0, 0) < 0) {
|
||||
uwsgi_error("prctl()");
|
||||
exit(1);
|
||||
}
|
||||
#else
|
||||
if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0) < 0) {
|
||||
uwsgi_error("prctl()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
uwsgi_log("capabilities applied for vassal %s (pid: %d)\n", n_ui->name, (int) getpid());
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
|
||||
if (setgid(n_ui->gid)) {
|
||||
@@ -1025,24 +1099,39 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
|
||||
int counter = 4;
|
||||
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
|
||||
while (uct) {
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
uct = uwsgi.vassals_includes;
|
||||
while (uct) {
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
struct uwsgi_string_list *uct;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates_before) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_includes_before) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_set) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates) counter += 2;
|
||||
uwsgi_foreach(uct, uwsgi.vassals_includes) counter += 2;
|
||||
|
||||
char **vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
|
||||
// set args
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
vassal_argv[0] = uwsgi.emperor_wrapper ? uwsgi.emperor_wrapper: uwsgi.binary_path;
|
||||
|
||||
// reset counter
|
||||
counter = 1;
|
||||
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates_before) {
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
}
|
||||
|
||||
uwsgi_foreach (uct, uwsgi.vassals_includes_before) {
|
||||
vassal_argv[counter] = "--include";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
}
|
||||
|
||||
uwsgi_foreach (uct, uwsgi.vassals_set) {
|
||||
vassal_argv[counter] = "--set";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
}
|
||||
|
||||
char *colon = NULL;
|
||||
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(n_ui->name, ':');
|
||||
if (colon) {
|
||||
@@ -1050,62 +1139,58 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
}
|
||||
// initialize to a default value
|
||||
vassal_argv[1] = "--inherit";
|
||||
vassal_argv[counter] = "--inherit";
|
||||
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
|
||||
vassal_argv[1] = "--xml";
|
||||
vassal_argv[counter] = "--xml";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
|
||||
vassal_argv[1] = "--ini";
|
||||
vassal_argv[counter] = "--ini";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
vassal_argv[counter] = "--yaml";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
vassal_argv[counter] = "--yaml";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
|
||||
vassal_argv[1] = "--json";
|
||||
vassal_argv[counter] = "--json";
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
vassal_argv[counter] = "--json";
|
||||
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
|
||||
while(usl) {
|
||||
if (uwsgi_endswith(n_ui->name, usl->value)) {
|
||||
vassal_argv[1] = "--config";
|
||||
vassal_argv[counter] = "--config";
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
if (colon) {
|
||||
colon[0] = ':';
|
||||
}
|
||||
// start config filename...
|
||||
counter++;
|
||||
|
||||
|
||||
vassal_argv[2] = n_ui->name;
|
||||
vassal_argv[counter] = n_ui->name;
|
||||
if (uwsgi.emperor_magic_exec) {
|
||||
if (!access(n_ui->name, R_OK | X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
|
||||
vassal_argv[counter] = uwsgi_concat2("exec://", n_ui->name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
|
||||
vassal_argv[counter] = uwsgi_concat2("emperor://", n_ui->name);
|
||||
}
|
||||
|
||||
counter = 3;
|
||||
uct = uwsgi.vassals_templates;
|
||||
while (uct) {
|
||||
// start templates,includes,inherit...
|
||||
counter++;
|
||||
|
||||
uwsgi_foreach(uct, uwsgi.vassals_templates) {
|
||||
vassal_argv[counter] = "--inherit";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
uct = uwsgi.vassals_includes;
|
||||
while (uct) {
|
||||
uwsgi_foreach (uct, uwsgi.vassals_includes) {
|
||||
vassal_argv[counter] = "--include";
|
||||
vassal_argv[counter + 1] = uct->value;
|
||||
counter += 2;
|
||||
uct = uct->next;
|
||||
}
|
||||
|
||||
vassal_argv[counter] = NULL;
|
||||
@@ -1121,18 +1206,7 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
}
|
||||
uwsgi_remap_fd(0, "/dev/null");
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
@@ -1471,7 +1545,8 @@ void emperor_loop() {
|
||||
ssize_t rlen = read(interesting_fd, &byte, 1);
|
||||
if (rlen <= 0) {
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
event_queue_del_fd(uwsgi.emperor_queue, interesting_fd, event_queue_read());
|
||||
emperor_curse(ui_current);
|
||||
}
|
||||
else {
|
||||
if (byte == 17) {
|
||||
@@ -1577,14 +1652,8 @@ void emperor_loop() {
|
||||
ui_current = ui;
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
if (ui_current->status == 1) {
|
||||
if (ui_current->config)
|
||||
free(ui_current->config);
|
||||
// SAFE
|
||||
emperor_del(ui_current);
|
||||
break;
|
||||
}
|
||||
else if (ui_current->pid == diedpid) {
|
||||
time_t now = uwsgi_now();
|
||||
if (ui_current->pid == diedpid) {
|
||||
if (ui_current->status == 0) {
|
||||
// respawn an accidentally dead instance if its exit code is not UWSGI_EXILE_CODE
|
||||
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXILE_CODE) {
|
||||
@@ -1607,6 +1676,13 @@ void emperor_loop() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (ui_current->cursed_at > 0 && now - ui_current->cursed_at >= uwsgi.emperor_curse_tolerance) {
|
||||
ui_current->cursed_at = now;
|
||||
if (kill(ui_current->pid, SIGKILL)) {
|
||||
uwsgi_error("[emperor] kill");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1703,6 +1779,8 @@ void emperor_send_stats(int fd) {
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_run", (unsigned long long) c_ui->last_run))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "cursed", (unsigned long long) c_ui->cursed_at))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
|
||||
goto end0;
|
||||
|
||||
@@ -1846,6 +1924,46 @@ void uwsgi_emperor_start() {
|
||||
}
|
||||
|
||||
void uwsgi_check_emperor() {
|
||||
char *emperor_fd_pass = getenv("UWSGI_EMPEROR_PROXY");
|
||||
if (emperor_fd_pass) {
|
||||
for(;;) {
|
||||
int proxy_fd = uwsgi_connect(emperor_fd_pass, 30, 0);
|
||||
if (proxy_fd < 0) {
|
||||
uwsgi_error("uwsgi_check_emperor()/uwsgi_connect()");
|
||||
sleep(1);
|
||||
continue;
|
||||
}
|
||||
int count = 2;
|
||||
int *fds = uwsgi_attach_fd(proxy_fd, &count, "uwsgi-emperor", 13);
|
||||
if (fds && count > 0) {
|
||||
char *env_emperor_fd = uwsgi_num2str(fds[0]);
|
||||
if (setenv("UWSGI_EMPEROR_FD", env_emperor_fd, 1)) {
|
||||
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD)");
|
||||
free(env_emperor_fd);
|
||||
int i; for(i=0;i<count;i++) close(fds[i]);
|
||||
goto next;
|
||||
}
|
||||
free(env_emperor_fd);
|
||||
if (count > 1) {
|
||||
char *env_emperor_fd_config = uwsgi_num2str(fds[1]);
|
||||
if (setenv("UWSGI_EMPEROR_FD_CONFIG", env_emperor_fd_config, 1)) {
|
||||
uwsgi_error("uwsgi_check_emperor()/setenv(UWSGI_EMPEROR_FD_CONFIG)");
|
||||
free(env_emperor_fd_config);
|
||||
int i; for(i=0;i<count;i++) close(fds[i]);
|
||||
goto next;
|
||||
}
|
||||
free(env_emperor_fd_config);
|
||||
}
|
||||
break;
|
||||
}
|
||||
next:
|
||||
if (fds) free(fds);
|
||||
close(proxy_fd);
|
||||
sleep(1);
|
||||
}
|
||||
unsetenv("UWSGI_EMPEROR_PROXY");
|
||||
}
|
||||
|
||||
char *emperor_env = getenv("UWSGI_EMPEROR_FD");
|
||||
if (emperor_env) {
|
||||
uwsgi.has_emperor = 1;
|
||||
@@ -1901,3 +2019,89 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor() {
|
||||
char byte;
|
||||
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("received message %d from emperor\n", byte);
|
||||
// remove me
|
||||
if (byte == 0) {
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
}
|
||||
// reload me
|
||||
else if (byte == 1) {
|
||||
// un-lazy the stack to trigger a real reload
|
||||
uwsgi.lazy = 0;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("lost connection with my emperor !!!\n");
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
sleep(2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor_proxy() {
|
||||
|
||||
struct sockaddr_un epsun;
|
||||
socklen_t epsun_len = sizeof(struct sockaddr_un);
|
||||
|
||||
int ep_client = accept(uwsgi.emperor_fd_proxy, (struct sockaddr *) &epsun, &epsun_len);
|
||||
if (ep_client < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_emperor_proxy()/accept()");
|
||||
return;
|
||||
}
|
||||
|
||||
int num_fds = 1;
|
||||
if (uwsgi.emperor_fd_config > -1) num_fds++;
|
||||
|
||||
struct msghdr ep_msg;
|
||||
void *ep_msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * num_fds));
|
||||
struct iovec ep_iov[2];
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
ep_iov[0].iov_base = "uwsgi-emperor";
|
||||
ep_iov[0].iov_len = 13;
|
||||
ep_iov[1].iov_base = &num_fds;
|
||||
ep_iov[1].iov_len = sizeof(int);
|
||||
|
||||
ep_msg.msg_name = NULL;
|
||||
ep_msg.msg_namelen = 0;
|
||||
|
||||
ep_msg.msg_iov = ep_iov;
|
||||
ep_msg.msg_iovlen = 2;
|
||||
|
||||
ep_msg.msg_flags = 0;
|
||||
ep_msg.msg_control = ep_msg_control;
|
||||
ep_msg.msg_controllen = CMSG_SPACE(sizeof(int) * num_fds);
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&ep_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN(sizeof(int) * num_fds);
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
unsigned char *ep_fd_ptr = CMSG_DATA(cmsg);
|
||||
|
||||
memcpy(ep_fd_ptr, &uwsgi.emperor_fd, sizeof(int));
|
||||
if (num_fds > 1) {
|
||||
memcpy(ep_fd_ptr + sizeof(int), &uwsgi.emperor_fd_config, sizeof(int));
|
||||
}
|
||||
|
||||
if (sendmsg(ep_client, &ep_msg, 0) < 0) {
|
||||
uwsgi_error("uwsgi_master_manage_emperor_proxy()/sendmsg()");
|
||||
}
|
||||
|
||||
free(ep_msg_control);
|
||||
|
||||
close(ep_client);
|
||||
}
|
||||
|
||||
+1
-1
@@ -99,7 +99,7 @@ int uwsgi_master_fifo() {
|
||||
}
|
||||
|
||||
int uwsgi_master_fifo_manage(int fd) {
|
||||
char cmd;
|
||||
unsigned char cmd;
|
||||
ssize_t rlen = read(fd, &cmd, 1);
|
||||
if (rlen < 0) {
|
||||
if (uwsgi_is_again()) return 0;
|
||||
|
||||
@@ -38,6 +38,7 @@ void uwsgi_fsmon_setup() {
|
||||
char *space = strchr(copy, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
|
||||
free(copy);
|
||||
goto next;
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
@@ -70,6 +70,7 @@ void gateway_respawn(int id) {
|
||||
|
||||
if (gw_pid == 0) {
|
||||
uwsgi_fixup_fds(0, 0, ug);
|
||||
uwsgi_close_all_sockets();
|
||||
if (uwsgi.master_as_root)
|
||||
uwsgi_as_root();
|
||||
#ifdef __linux__
|
||||
|
||||
+21
-1
@@ -17,7 +17,7 @@ uint32_t djb33x_hash(char *key, uint64_t keylen) {
|
||||
|
||||
// Murmur2 hash Copyright (C) Austin Appleby
|
||||
// adapted from nginx
|
||||
uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
static uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
|
||||
uint32_t h, k;
|
||||
uint8_t *ukey = (uint8_t *) key;
|
||||
@@ -56,6 +56,23 @@ uint32_t murmur2_hash(char *key, uint64_t keylen) {
|
||||
return h;
|
||||
}
|
||||
|
||||
static uint32_t random_hash(char *key, uint64_t keylen) {
|
||||
return (uint32_t) rand();
|
||||
}
|
||||
|
||||
/*
|
||||
not atomic, avoid its use in multithreaded modes
|
||||
*/
|
||||
static uint32_t rr_hash(char *key, uint64_t keylen) {
|
||||
static uint32_t rr = 0;
|
||||
uint32_t max_value = uwsgi_str_num(key, keylen);
|
||||
uint32_t ret = rr;
|
||||
rr++;
|
||||
if (rr > max_value) {
|
||||
rr = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *name) {
|
||||
struct uwsgi_hash_algo *uha = uwsgi.hash_algos;
|
||||
@@ -90,4 +107,7 @@ void uwsgi_hash_algo_register(char *name, uint32_t (*func)(char *, uint64_t)) {
|
||||
void uwsgi_hash_algo_register_all() {
|
||||
uwsgi_hash_algo_register("djb33x", djb33x_hash);
|
||||
uwsgi_hash_algo_register("murmur2", murmur2_hash);
|
||||
uwsgi_hash_algo_register("random", random_hash);
|
||||
uwsgi_hash_algo_register("rand", random_hash);
|
||||
uwsgi_hash_algo_register("rr", rr_hash);
|
||||
}
|
||||
|
||||
+5
-7
@@ -51,6 +51,7 @@ struct http_status_codes hsc[] = {
|
||||
{"503", "Service Unavailable"},
|
||||
{"504", "Gateway Timeout"},
|
||||
{"505", "HTTP Version Not Supported"},
|
||||
{"509", "Bandwidth Limit Exceeded"},
|
||||
{"", NULL},
|
||||
};
|
||||
|
||||
@@ -75,10 +76,12 @@ void uwsgi_init_default() {
|
||||
uwsgi.original_log_fd = -1;
|
||||
|
||||
uwsgi.emperor_fd_config = -1;
|
||||
uwsgi.emperor_fd_proxy = -1;
|
||||
// default emperor scan frequency
|
||||
uwsgi.emperor_freq = 3;
|
||||
uwsgi.emperor_throttle = 1000;
|
||||
uwsgi.emperor_heartbeat = 30;
|
||||
uwsgi.emperor_curse_tolerance = 30;
|
||||
// max 3 minutes throttling
|
||||
uwsgi.emperor_max_throttle = 1000 * 180;
|
||||
uwsgi.emperor_pid = -1;
|
||||
@@ -176,6 +179,7 @@ void uwsgi_init_default() {
|
||||
// clear reforked status
|
||||
uwsgi.master_is_reforked = 0;
|
||||
|
||||
uwsgi.master_fifo_fd = -1;
|
||||
uwsgi_master_fifo_prepare();
|
||||
}
|
||||
|
||||
@@ -342,7 +346,6 @@ void uwsgi_setup_workers() {
|
||||
uwsgi.workers[i].signal_pipe[0] = -1;
|
||||
uwsgi.workers[i].signal_pipe[1] = -1;
|
||||
snprintf(uwsgi.workers[i].name, 0xff, "uWSGI worker %d", i);
|
||||
snprintf(uwsgi.workers[i].snapshot_name, 0xff, "uWSGI snapshot %d", i);
|
||||
}
|
||||
|
||||
uint64_t total_memory = (sizeof(struct uwsgi_app) * uwsgi.max_apps) + (sizeof(struct uwsgi_core) * uwsgi.cores) + (sizeof(void *) * uwsgi.max_apps * uwsgi.cores) + (uwsgi.buffer_size * uwsgi.cores) + (sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
|
||||
@@ -444,11 +447,6 @@ void sanitize_args() {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.auto_snapshot > 0 && uwsgi.auto_snapshot > uwsgi.numproc) {
|
||||
uwsgi_log("invalid auto-snapshot value: must be <= than processes\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0 && uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] >= uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]) {
|
||||
uwsgi_log("invalid min-worker-lifetime value (%d), must be lower than max-worker-lifetime (%d)\n",
|
||||
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME], uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME]);
|
||||
@@ -463,7 +461,7 @@ void sanitize_args() {
|
||||
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
|
||||
exit(1);
|
||||
}
|
||||
if ( uwsgi.cheaper_rss_limit_soft && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
|
||||
if ( uwsgi.cheaper_rss_limit_hard && uwsgi.cheaper_rss_limit_hard <= uwsgi.cheaper_rss_limit_soft) {
|
||||
uwsgi_log("cheaper-rss-limit-hard value must be higher than cheaper-rss-limit-soft value\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -116,48 +116,31 @@ end:
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
extremely complex function for reading resources (files, url...)
|
||||
need a lot of refactoring...
|
||||
*/
|
||||
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
|
||||
static char *uwsgi_scheme_fd(char *url, size_t *size, int add_zero) {
|
||||
int fd = atoi(url);
|
||||
return uwsgi_read_fd(fd, size, add_zero);
|
||||
}
|
||||
|
||||
int fd;
|
||||
struct stat sb;
|
||||
char *buffer = NULL;
|
||||
static char *uwsgi_scheme_exec(char *url, size_t *size, int add_zero) {
|
||||
int cpipe[2];
|
||||
if (pipe(cpipe)) {
|
||||
uwsgi_error("pipe()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_run_command(url, NULL, cpipe[1]);
|
||||
char *buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_http(char *url, size_t *size, int add_zero) {
|
||||
char byte;
|
||||
ssize_t len;
|
||||
char *uri, *colon;
|
||||
char *domain;
|
||||
char *ip;
|
||||
int body = 0;
|
||||
char *magic_buf;
|
||||
int body = 0;
|
||||
char *buffer = NULL;
|
||||
|
||||
// stdin ?
|
||||
if (!strcmp(url, "-")) {
|
||||
buffer = uwsgi_read_fd(0, size, add_zero);
|
||||
}
|
||||
// fd ?
|
||||
else if (!strncmp("fd://", url, 5)) {
|
||||
fd = atoi(url + 5);
|
||||
buffer = uwsgi_read_fd(fd, size, add_zero);
|
||||
}
|
||||
// exec ?
|
||||
else if (!strncmp("exec://", url, 5)) {
|
||||
int cpipe[2];
|
||||
if (pipe(cpipe)) {
|
||||
uwsgi_error("pipe()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_run_command(url + 7, NULL, cpipe[1]);
|
||||
buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
}
|
||||
// http url ?
|
||||
else if (!strncmp("http://", url, 7)) {
|
||||
domain = url + 7;
|
||||
uri = strchr(domain, '/');
|
||||
char *domain = url;
|
||||
char *uri = strchr(domain, '/');
|
||||
if (!uri) {
|
||||
uwsgi_log("invalid http url\n");
|
||||
exit(1);
|
||||
@@ -165,14 +148,14 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
uri[0] = 0;
|
||||
uwsgi_log("domain: %s\n", domain);
|
||||
|
||||
colon = uwsgi_get_last_char(domain, ':');
|
||||
char *colon = uwsgi_get_last_char(domain, ':');
|
||||
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
|
||||
|
||||
ip = uwsgi_resolve_ip(domain);
|
||||
char *ip = uwsgi_resolve_ip(domain);
|
||||
if (!ip) {
|
||||
uwsgi_log("unable to resolve address %s\n", domain);
|
||||
exit(1);
|
||||
@@ -186,9 +169,10 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
ip = uwsgi_concat2(ip, ":80");
|
||||
}
|
||||
|
||||
fd = uwsgi_connect(ip, 0, 0);
|
||||
int fd = uwsgi_connect(ip, 0, 0);
|
||||
|
||||
if (fd < 0) {
|
||||
uwsgi_error("uwsgi_scheme_http()/connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -196,18 +180,18 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
|
||||
uri[0] = '/';
|
||||
|
||||
len = write(fd, "GET ", 4);
|
||||
len = write(fd, uri, strlen(uri));
|
||||
len = write(fd, " HTTP/1.0\r\n", 11);
|
||||
len = write(fd, "Host: ", 6);
|
||||
if (write(fd, "GET ", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, uri, strlen(uri)) != (ssize_t) strlen(uri)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, " HTTP/1.0\r\n", 11) != 11) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, "Host: ", 6) != 6) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
|
||||
uri[0] = 0;
|
||||
len = write(fd, domain, strlen(domain));
|
||||
if (write(fd, domain, strlen(domain)) != (ssize_t) strlen(domain)) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
uri[0] = '/';
|
||||
|
||||
len = write(fd, "\r\nUser-Agent: uWSGI on ", 23);
|
||||
len = write(fd, uwsgi.hostname, uwsgi.hostname_len);
|
||||
len = write(fd, "\r\n\r\n", 4);
|
||||
if (write(fd, "\r\nUser-Agent: uWSGI on ", 23) != 23) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, uwsgi.hostname, uwsgi.hostname_len) != uwsgi.hostname_len) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
if (write(fd, "\r\n\r\n", 4) != 4) { uwsgi_error("uwsgi_scheme_http()/write()"); exit(1);}
|
||||
|
||||
int http_status_code_ptr = 0;
|
||||
|
||||
@@ -264,57 +248,233 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
buffer[*size - 1] = 0;
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static char *uwsgi_scheme_emperor(char *url, size_t *size, int add_zero) {
|
||||
|
||||
if (uwsgi.emperor_fd_config < 0) {
|
||||
uwsgi_log("this is not a vassal instance\n");
|
||||
exit(1);
|
||||
}
|
||||
else if (!strncmp("emperor://", url, 10)) {
|
||||
if (uwsgi.emperor_fd_config < 0) {
|
||||
uwsgi_log("this is not a vassal instance\n");
|
||||
ssize_t rlen;
|
||||
struct uwsgi_header uh;
|
||||
size_t remains = 4;
|
||||
char *ptr = (char *) &uh;
|
||||
while(remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ssize_t rlen;
|
||||
*size = 0;
|
||||
struct uwsgi_header uh;
|
||||
size_t remains = 4;
|
||||
char *ptr = (char *) &uh;
|
||||
while(remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config header from %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
}
|
||||
|
||||
remains = uh.pktsize;
|
||||
if (!remains) {
|
||||
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
|
||||
remains = uh.pktsize;
|
||||
if (!remains) {
|
||||
uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *buffer = uwsgi_calloc(remains + add_zero);
|
||||
ptr = buffer;
|
||||
while (remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config from %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
}
|
||||
|
||||
*size = uh.pktsize + add_zero;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_data(char *url, size_t *size, int add_zero) {
|
||||
char *buffer = NULL;
|
||||
int fd = open(uwsgi.binary_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
int slot = atoi(url);
|
||||
if (slot < 0) {
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("requesting binary data slot %d\n", slot);
|
||||
off_t fo = lseek(fd, 0, SEEK_END);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
int i = 0;
|
||||
uint64_t datasize = 0;
|
||||
for (i = 0; i <= slot; i++) {
|
||||
fo = lseek(fd, -8, SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
ssize_t len = read(fd, &datasize, 8);
|
||||
if (len != 8) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
if (datasize == 0) {
|
||||
uwsgi_log("0 size binary data !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
fo = lseek(fd, -(datasize + 8), SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
buffer = uwsgi_calloc(remains + add_zero);
|
||||
ptr = buffer;
|
||||
while (remains) {
|
||||
int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
|
||||
if (ret <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
rlen = read(uwsgi.emperor_fd_config, ptr, remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
|
||||
exit(1);
|
||||
}
|
||||
ptr+=rlen;
|
||||
remains-=rlen;
|
||||
if (i == slot) {
|
||||
*size = datasize;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
len = read(fd, buffer, datasize);
|
||||
if (len != (ssize_t) datasize) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
*size = uh.pktsize + add_zero;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_call(char *url, size_t *size, int add_zero) {
|
||||
char *(*func)(void) = dlsym(RTLD_DEFAULT, url);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to find symbol %s\n", url);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
char *s = func();
|
||||
if (!s) {
|
||||
uwsgi_log("called symbol %s did not return a string\n", url);
|
||||
exit(1);
|
||||
}
|
||||
*size = strlen(s);
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
char *buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, s, strlen(s));
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
static char *uwsgi_scheme_sym(char *url, size_t *size, int add_zero) {
|
||||
void *sym_start_ptr = NULL, *sym_end_ptr = NULL;
|
||||
char **raw_symbol = dlsym(RTLD_DEFAULT, url);
|
||||
if (raw_symbol) {
|
||||
sym_start_ptr = *raw_symbol;
|
||||
sym_end_ptr = sym_start_ptr + strlen(sym_start_ptr);
|
||||
goto found;
|
||||
}
|
||||
char *symbol = uwsgi_concat3("_binary_", url, "_start");
|
||||
sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_start_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
symbol = uwsgi_concat3("_binary_", url, "_end");
|
||||
sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_end_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
|
||||
found:
|
||||
|
||||
*size = sym_end_ptr - sym_start_ptr;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
char *buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *uwsgi_scheme_section(char *url, size_t *size, int add_zero) {
|
||||
#ifdef UWSGI_ELF
|
||||
size_t s_len = 0;
|
||||
char *buffer = uwsgi_elf_section(uwsgi.binary_path, url, &s_len);
|
||||
if (!buffer) {
|
||||
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
*size = s_len;
|
||||
if (add_zero)
|
||||
*size += 1;
|
||||
return buffer;
|
||||
#else
|
||||
uwsgi_log("section:// scheme not supported on this platform\n");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *uwsgi_register_scheme(char *name, char * (*func)(char *, size_t *, int)) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.schemes) {
|
||||
if (!strcmp(usl->value, name)) goto found;
|
||||
}
|
||||
|
||||
usl = uwsgi_string_new_list(&uwsgi.schemes, name);
|
||||
|
||||
found:
|
||||
usl->custom_ptr = func;
|
||||
return usl;
|
||||
}
|
||||
|
||||
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {
|
||||
|
||||
struct stat sb;
|
||||
char *buffer = NULL;
|
||||
ssize_t len;
|
||||
char *magic_buf;
|
||||
int fd;
|
||||
|
||||
*size = 0;
|
||||
|
||||
// stdin ?
|
||||
if (!strcmp(url, "-")) {
|
||||
buffer = uwsgi_read_fd(0, size, add_zero);
|
||||
goto end;
|
||||
}
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
else if (url[0] == 0) {
|
||||
*size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG;
|
||||
@@ -324,108 +484,22 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
else if (!strncmp("data://", url, 7)) {
|
||||
fd = open(uwsgi.binary_path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
int slot = atoi(url + 7);
|
||||
if (slot < 0) {
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("requesting binary data slot %d\n", slot);
|
||||
off_t fo = lseek(fd, 0, SEEK_END);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
int i = 0;
|
||||
uint64_t datasize = 0;
|
||||
for (i = 0; i <= slot; i++) {
|
||||
fo = lseek(fd, -9, SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
ssize_t len = read(fd, &datasize, 8);
|
||||
if (len != 8) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
if (datasize == 0) {
|
||||
uwsgi_log("0 size binary data !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
fo = lseek(fd, -(datasize + 9), SEEK_CUR);
|
||||
if (fo < 0) {
|
||||
uwsgi_error("lseek()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (i == slot) {
|
||||
*size = datasize;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
len = read(fd, buffer, datasize);
|
||||
if (len != (ssize_t) datasize) {
|
||||
uwsgi_error("read()");
|
||||
uwsgi_log("invalid binary data slot requested\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!strncmp("sym://", url, 6)) {
|
||||
char *symbol = uwsgi_concat3("_binary_", url + 6, "_start");
|
||||
void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_start_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
symbol = uwsgi_concat3("_binary_", url + 6, "_end");
|
||||
void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
|
||||
if (!sym_end_ptr) {
|
||||
uwsgi_log("unable to find symbol %s\n", symbol);
|
||||
exit(1);
|
||||
}
|
||||
free(symbol);
|
||||
struct uwsgi_string_list *usl = uwsgi_check_scheme(url);
|
||||
if (!usl) goto fallback;
|
||||
|
||||
*size = sym_end_ptr - sym_start_ptr;
|
||||
if (add_zero) {
|
||||
*size += 1;
|
||||
}
|
||||
buffer = uwsgi_malloc(*size);
|
||||
memset(buffer, 0, *size);
|
||||
memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);
|
||||
|
||||
}
|
||||
#ifdef UWSGI_ELF
|
||||
else if (!strncmp("section://", url, 10)) {
|
||||
size_t s_len = 0;
|
||||
buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len);
|
||||
if (!buffer) {
|
||||
uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
|
||||
exit(1);
|
||||
}
|
||||
*size = s_len;
|
||||
if (add_zero)
|
||||
*size += 1;
|
||||
}
|
||||
#endif
|
||||
char *(*func)(char *, size_t *, int) = (char *(*)(char *, size_t *, int)) usl->custom_ptr;
|
||||
buffer = func(url + usl->len + 3, size, add_zero);
|
||||
if (buffer) goto end;
|
||||
// never here !!!
|
||||
uwsgi_log("unable to parse config file %s\n", url);
|
||||
exit(1);
|
||||
|
||||
// fallback to file
|
||||
else {
|
||||
fallback:
|
||||
fd = open(url, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(url);
|
||||
@@ -457,7 +531,6 @@ char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_tab
|
||||
|
||||
if (add_zero)
|
||||
buffer[sb.st_size] = 0;
|
||||
}
|
||||
|
||||
end:
|
||||
|
||||
@@ -870,12 +943,12 @@ int uwsgi_read_whole_true_nb(int fd, char *buf, size_t remains, int timeout) {
|
||||
}
|
||||
|
||||
/*
|
||||
this is a pretty magic function used for read a full uwsgi response
|
||||
this is a pretty magic function used for reading a full uwsgi response
|
||||
it is true non blocking, so you can use it in request plugins
|
||||
buffer is expected to be at least 4 bytes, rlen is a get/set value
|
||||
*/
|
||||
|
||||
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout) {
|
||||
int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout, uint8_t *modifier1, uint8_t *modifier2) {
|
||||
if (*rlen < 4) return -1;
|
||||
char *buf = *buffer;
|
||||
int ret;
|
||||
@@ -906,6 +979,10 @@ readok:
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) buf;
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
if (modifier1)
|
||||
*modifier1 = uh->modifier1;
|
||||
if (modifier2)
|
||||
*modifier2 = uh->modifier2;
|
||||
|
||||
if (pktsize > *rlen) {
|
||||
char *tmp_buf = realloc(buf, pktsize);
|
||||
@@ -1097,3 +1174,44 @@ int uwsgi_ready_fd(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->async_ready_fd) return wsgi_req->async_last_ready_fd;
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_setup_schemes() {
|
||||
uwsgi_register_scheme("emperor", uwsgi_scheme_emperor);
|
||||
uwsgi_register_scheme("http", uwsgi_scheme_http);
|
||||
uwsgi_register_scheme("data", uwsgi_scheme_data);
|
||||
uwsgi_register_scheme("sym", uwsgi_scheme_sym);
|
||||
uwsgi_register_scheme("section", uwsgi_scheme_section);
|
||||
uwsgi_register_scheme("fd", uwsgi_scheme_fd);
|
||||
uwsgi_register_scheme("exec", uwsgi_scheme_exec);
|
||||
uwsgi_register_scheme("call", uwsgi_scheme_call);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *uwsgi_check_scheme(char *file) {
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.schemes) {
|
||||
char *url = uwsgi_concat2(usl->value, "://");
|
||||
int ret = uwsgi_startswith(file, url, strlen(url));
|
||||
free(url);
|
||||
if (!ret) return usl;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_remap_fd(int fd, char *filename) {
|
||||
|
||||
int fdin = open(filename, O_RDWR);
|
||||
if (fdin < 0) {
|
||||
uwsgi_error_open(filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* stdin */
|
||||
if (fdin != fd) {
|
||||
if (dup2(fdin, fd) < 0) {
|
||||
uwsgi_error("uwsgi_remap_fd()/dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fdin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -106,6 +106,8 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
|
||||
config_iter = json_object_iter_next(config, config_iter);
|
||||
}
|
||||
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+15
-2
@@ -498,7 +498,7 @@ void uwsgi_check_logrotate(void) {
|
||||
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
|
||||
}
|
||||
|
||||
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
if (uwsgi.log_maxsize > 0 && (uint64_t) uwsgi.shared->logsize > uwsgi.log_maxsize) {
|
||||
need_rotation = 1;
|
||||
}
|
||||
|
||||
@@ -575,6 +575,7 @@ void uwsgi_log_reopen() {
|
||||
if (uwsgi.original_log_fd < 0) {
|
||||
uwsgi_error_open(uwsgi.logfile);
|
||||
grace_them_all(0);
|
||||
return;
|
||||
}
|
||||
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
|
||||
if (ret > 0) {
|
||||
@@ -980,6 +981,12 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 0;
|
||||
}
|
||||
}
|
||||
// metric
|
||||
else if (logchunk->type == 4) {
|
||||
int64_t metric = uwsgi_metric_get(logchunk->ptr, NULL);
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = uwsgi_64bit2str(metric);
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = strlen(uwsgi.logvectors[wsgi_req->async_id][pos].iov_base);
|
||||
}
|
||||
|
||||
if (uwsgi.logvectors[wsgi_req->async_id][pos].iov_len == 0 && logchunk->type != 0) {
|
||||
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = (char *) empty_var;
|
||||
@@ -1231,6 +1238,7 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
1 -> offsetof variable
|
||||
2 -> logvar
|
||||
3 -> func
|
||||
4 -> metric
|
||||
*/
|
||||
|
||||
logchunk->type = variable;
|
||||
@@ -1397,6 +1405,11 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
logchunk->func = uwsgi_lf_headers;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_starts_with(ptr, len, "metric.", 7)) {
|
||||
logchunk->type = 4;
|
||||
logchunk->ptr = uwsgi_concat2n(ptr+7, len - 7, "", 0);
|
||||
logchunk->free = 1;
|
||||
}
|
||||
// logvar
|
||||
else {
|
||||
logchunk->type = 2;
|
||||
@@ -1841,7 +1854,7 @@ void uwsgi_log_encoder_parse_vars(struct uwsgi_log_encoder *ule) {
|
||||
/*
|
||||
// format: foo ${var} bar
|
||||
msg (the logline)
|
||||
msgnl (the logine with newline)
|
||||
msgnl (the logline with newline)
|
||||
unix (the time_t value)
|
||||
micros (current microseconds)
|
||||
strftime (strftime)
|
||||
|
||||
+82
-99
@@ -2,15 +2,30 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_restore_auto_snapshot(int signum) {
|
||||
void uwsgi_update_load_counters() {
|
||||
|
||||
if (uwsgi.workers[1].snapshot > 0) {
|
||||
uwsgi.restore_snapshot = 1;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[WARNING] no snapshot available\n");
|
||||
int i;
|
||||
uint64_t busy_workers = 0;
|
||||
uint64_t idle_workers = 0;
|
||||
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi_worker_is_busy(i) == 0) {
|
||||
idle_workers++;
|
||||
}
|
||||
else {
|
||||
busy_workers++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (busy_workers >= (uint64_t) uwsgi.numproc) {
|
||||
ushared->overloaded++;
|
||||
}
|
||||
|
||||
ushared->busy_workers = busy_workers;
|
||||
ushared->idle_workers = idle_workers;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_block_signal(int signum) {
|
||||
@@ -32,24 +47,25 @@ void uwsgi_unblock_signal(int signum) {
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_udp(int udp_fd) {
|
||||
char buf[4096];
|
||||
struct sockaddr_in udp_client;
|
||||
char udp_client_addr[16];
|
||||
int i;
|
||||
|
||||
socklen_t udp_len = sizeof(udp_client);
|
||||
ssize_t rlen = recvfrom(udp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
ssize_t rlen = recvfrom(udp_fd, buf, 4096, 0, (struct sockaddr *) &udp_client, &udp_len);
|
||||
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("recvfrom()");
|
||||
uwsgi_error("uwsgi_master_manage_udp()/recvfrom()");
|
||||
}
|
||||
else if (rlen > 0) {
|
||||
|
||||
memset(udp_client_addr, 0, 16);
|
||||
if (inet_ntop(AF_INET, &udp_client.sin_addr.s_addr, udp_client_addr, 16)) {
|
||||
if (uwsgi.wsgi_req->buffer[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
|
||||
if (buf[0] == UWSGI_MODIFIER_MULTICAST_ANNOUNCE) {
|
||||
}
|
||||
else if (uwsgi.wsgi_req->buffer[0] == 0x30 && uwsgi.snmp) {
|
||||
manage_snmp(udp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
|
||||
else if (buf[0] == 0x30 && uwsgi.snmp) {
|
||||
manage_snmp(udp_fd, (uint8_t *) buf, rlen, &udp_client);
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -57,7 +73,7 @@ void uwsgi_master_manage_udp(int udp_fd) {
|
||||
int udp_managed = 0;
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->manage_udp) {
|
||||
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, uwsgi.wsgi_req->buffer, rlen)) {
|
||||
if (uwsgi.p[i]->manage_udp(udp_client_addr, udp_client.sin_port, buf, rlen)) {
|
||||
udp_managed = 1;
|
||||
break;
|
||||
}
|
||||
@@ -66,74 +82,17 @@ void uwsgi_master_manage_udp(int udp_fd) {
|
||||
|
||||
// else a simple udp logger
|
||||
if (!udp_managed) {
|
||||
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, uwsgi.wsgi_req->buffer);
|
||||
uwsgi_log("[udp:%s:%d] %.*s", udp_client_addr, ntohs(udp_client.sin_port), (int) rlen, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_error("inet_ntop()");
|
||||
uwsgi_error("uwsgi_master_manage_udp()/inet_ntop()");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_manage_emperor() {
|
||||
char byte;
|
||||
ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
|
||||
if (rlen > 0) {
|
||||
uwsgi_log_verbose("received message %d from emperor\n", byte);
|
||||
// remove me
|
||||
if (byte == 0) {
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
}
|
||||
// reload me
|
||||
else if (byte == 1) {
|
||||
// un-lazy the stack to trigger a real reload
|
||||
uwsgi.lazy = 0;
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
grace_them_all(0);
|
||||
uwsgi_unblock_signal(SIGHUP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("lost connection with my emperor !!!\n");
|
||||
close(uwsgi.emperor_fd);
|
||||
if (!uwsgi.status.brutally_reloading)
|
||||
kill_them_all(0);
|
||||
sleep(2);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_master_restore_snapshot() {
|
||||
int i, waitpid_status;
|
||||
uwsgi_log("[snapshot] restoring workers...\n");
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].pid == 0)
|
||||
continue;
|
||||
kill(uwsgi.workers[i].pid, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
uwsgi.workers[i].snapshot = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[i].pid = uwsgi.workers[i].snapshot;
|
||||
uwsgi.workers[i].snapshot = 0;
|
||||
kill(uwsgi.workers[i].pid, SIGURG);
|
||||
uwsgi_log("Restored uWSGI worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi.restore_snapshot = 0;
|
||||
}
|
||||
|
||||
void suspend_resume_them_all(int signum) {
|
||||
|
||||
int i;
|
||||
@@ -331,9 +290,6 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
uwsgi_unix_signal(SIGINT, kill_them_all);
|
||||
uwsgi_unix_signal(SIGUSR1, stats);
|
||||
if (uwsgi.auto_snapshot) {
|
||||
uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot);
|
||||
}
|
||||
|
||||
atexit(uwsgi_master_cleanup_hooks);
|
||||
|
||||
@@ -378,6 +334,7 @@ int master_loop(char **argv, char **environ) {
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_start_legions();
|
||||
#endif
|
||||
uwsgi_metrics_start_collector();
|
||||
|
||||
uwsgi_add_reload_fds();
|
||||
|
||||
@@ -387,7 +344,18 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi.wsgi_req->buffer = uwsgi.workers[0].cores[0].buffer;
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
|
||||
if (uwsgi.emperor_proxy) {
|
||||
uwsgi.emperor_fd_proxy = bind_to_unix(uwsgi.emperor_proxy, uwsgi.listen_queue, 0, 0);
|
||||
if (uwsgi.emperor_fd_proxy < 0) exit(1);
|
||||
if (chmod(uwsgi.emperor_proxy, S_IRUSR|S_IWUSR)) {
|
||||
uwsgi_error("[emperor-proxy] chmod()");
|
||||
exit(1);
|
||||
}
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd_proxy);
|
||||
}
|
||||
else {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.zerg_server) {
|
||||
@@ -507,6 +475,28 @@ int master_loop(char **argv, char **environ) {
|
||||
// fsmon
|
||||
uwsgi_fsmon_setup();
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.signal_timers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid signal timer syntax, must be: <signal> <seconds>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_add_timer(atoi(usl->value), atoi(space+1));
|
||||
*space = ' ';
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.rb_signal_timers) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid redblack signal timer syntax, must be: <signal> <seconds>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
uwsgi_signal_add_rb_timer(atoi(usl->value), atoi(space+1), 0);
|
||||
*space = ' ';
|
||||
}
|
||||
|
||||
// setup cheaper algos (can be stacked)
|
||||
uwsgi.cheaper_algo = uwsgi_cheaper_algo_spare;
|
||||
if (uwsgi.requested_cheaper_algo) {
|
||||
@@ -560,21 +550,6 @@ int master_loop(char **argv, char **environ) {
|
||||
// check for daemons (smart and dumb)
|
||||
uwsgi_daemons_smart_check();
|
||||
|
||||
|
||||
if (uwsgi.respawn_snapshots) {
|
||||
for (i = 1; i <= uwsgi.respawn_snapshots; i++) {
|
||||
if (uwsgi_respawn_worker(i))
|
||||
return 0;
|
||||
}
|
||||
|
||||
uwsgi.respawn_snapshots = 0;
|
||||
}
|
||||
|
||||
if (uwsgi.restore_snapshot) {
|
||||
uwsgi_master_restore_snapshot();
|
||||
continue;
|
||||
}
|
||||
|
||||
// cheaper management
|
||||
if (uwsgi.cheaper && !uwsgi.status.is_cheap && !uwsgi_instance_is_reloading && !uwsgi_instance_is_dying && !uwsgi.workers[0].suspended) {
|
||||
if (!uwsgi_calc_cheaper())
|
||||
@@ -604,8 +579,10 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
/* all processes ok, doing status scan after N seconds */
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
if (!check_interval)
|
||||
if (!check_interval) {
|
||||
check_interval = 1;
|
||||
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
|
||||
}
|
||||
|
||||
|
||||
// add unregistered file monitors
|
||||
@@ -640,14 +617,14 @@ int master_loop(char **argv, char **environ) {
|
||||
|
||||
if (ushared->rb_timers_cnt > 0) {
|
||||
min_timeout = uwsgi_min_rb_timer(rb_timers, NULL);
|
||||
if (min_timeout == NULL) {
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
}
|
||||
else {
|
||||
check_interval = min_timeout->value - uwsgi_now();
|
||||
if (check_interval <= 0) {
|
||||
if (min_timeout) {
|
||||
int delta = min_timeout->value - uwsgi_now();
|
||||
if (delta <= 0) {
|
||||
expire_rb_timeouts(rb_timers);
|
||||
check_interval = 0;
|
||||
}
|
||||
// if the timer expires before the check_interval, override it
|
||||
else if (delta < check_interval) {
|
||||
check_interval = delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -661,6 +638,9 @@ int master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
// update load counter
|
||||
uwsgi_update_load_counters();
|
||||
|
||||
|
||||
// check uwsgi-cron table
|
||||
if (ushared->cron_cnt) {
|
||||
@@ -701,8 +681,10 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_master_check_idle();
|
||||
|
||||
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
|
||||
if (!check_interval)
|
||||
if (!check_interval) {
|
||||
check_interval = 1;
|
||||
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = 1;
|
||||
}
|
||||
|
||||
|
||||
// get listen_queue status
|
||||
@@ -735,6 +717,7 @@ int master_loop(char **argv, char **environ) {
|
||||
uwsgi_master_check_mules_deadline();
|
||||
uwsgi_master_check_spoolers_deadline();
|
||||
uwsgi_master_check_crons_deadline();
|
||||
uwsgi_master_check_mountpoints();
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef MADV_MERGEABLE
|
||||
|
||||
@@ -118,6 +118,9 @@ void uwsgi_master_check_idle() {
|
||||
if (errno != ECHILD)
|
||||
uwsgi_error("uwsgi_master_check_idle()/waitpid()");
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[i].pid = 0;
|
||||
}
|
||||
}
|
||||
uwsgi_add_sockets_to_queue(uwsgi.master_queue, -1);
|
||||
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
|
||||
@@ -322,3 +325,14 @@ void uwsgi_master_check_crons_deadline() {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_master_check_mountpoints() {
|
||||
struct uwsgi_string_list *usl;
|
||||
uwsgi_foreach(usl, uwsgi.mountpoints_check) {
|
||||
if (uwsgi_check_mountpoint(usl->value)) {
|
||||
uwsgi_log_verbose("mountpoint %s failed, triggering detonation...\n", usl->value);
|
||||
uwsgi_nuclear_blast();
|
||||
//never here
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,11 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
|
||||
// emperor event ?
|
||||
if (uwsgi.has_emperor) {
|
||||
if (uwsgi.emperor_fd_proxy > -1 && interesting_fd == uwsgi.emperor_fd_proxy) {
|
||||
uwsgi_master_manage_emperor_proxy();
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (interesting_fd == uwsgi.emperor_fd) {
|
||||
uwsgi_master_manage_emperor();
|
||||
return 0;
|
||||
@@ -113,6 +118,7 @@ int uwsgi_master_manage_events(int interesting_fd) {
|
||||
reap_them_all(0);
|
||||
uwsgi_unblock_signal(SIGTERM);
|
||||
}
|
||||
if (usl->custom2 > 8) free(tmp);
|
||||
return 0;
|
||||
}
|
||||
usl = usl->next;
|
||||
|
||||
+77
-7
@@ -151,7 +151,13 @@ int uwsgi_calc_cheaper(void) {
|
||||
uwsgi.cheaper_fifo_delta = 0;
|
||||
}
|
||||
|
||||
if (!ignore_algo) needed_workers = uwsgi.cheaper_algo();
|
||||
// if cheaper limits wants to change worker count, then skip cheaper algo
|
||||
if (!needed_workers) needed_workers = uwsgi.cheaper_algo(!ignore_algo);
|
||||
// safe check to verify if cheaper algo obeyed ignore_algo value
|
||||
if (ignore_algo && needed_workers > 0) {
|
||||
uwsgi_log("BUG! cheaper algo returned %d but it cannot spawn any worker at this time!\n", needed_workers);
|
||||
needed_workers = 0;
|
||||
}
|
||||
|
||||
if (needed_workers > 0) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
@@ -189,7 +195,7 @@ int uwsgi_calc_cheaper(void) {
|
||||
}
|
||||
|
||||
// fake algo to allow control with the fifo
|
||||
int uwsgi_cheaper_algo_manual(void) {
|
||||
int uwsgi_cheaper_algo_manual(int can_spawn) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -228,7 +234,7 @@ int uwsgi_cheaper_algo_manual(void) {
|
||||
*/
|
||||
|
||||
|
||||
int uwsgi_cheaper_algo_spare(void) {
|
||||
int uwsgi_cheaper_algo_spare(int can_spawn) {
|
||||
|
||||
int i;
|
||||
static uint64_t overload_count = 0;
|
||||
@@ -252,7 +258,7 @@ int uwsgi_cheaper_algo_spare(void) {
|
||||
healthy:
|
||||
|
||||
// are we overloaded ?
|
||||
if (overload_count > uwsgi.cheaper_overload) {
|
||||
if (can_spawn && overload_count > uwsgi.cheaper_overload) {
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("overloaded !!!\n");
|
||||
@@ -320,7 +326,7 @@ healthy:
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_cheaper_algo_backlog(void) {
|
||||
int uwsgi_cheaper_algo_backlog(int can_spawn) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
@@ -329,7 +335,7 @@ int uwsgi_cheaper_algo_backlog(void) {
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
if (backlog > (int) uwsgi.cheaper_overload) {
|
||||
if (can_spawn && backlog > (int) uwsgi.cheaper_overload) {
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
@@ -865,6 +871,70 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi.has_metrics) {
|
||||
if (uwsgi_stats_key(us, "metrics"))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_object_open(us))
|
||||
goto end;
|
||||
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
struct uwsgi_metric *um = uwsgi.metrics;
|
||||
while(um) {
|
||||
int64_t um_val = *um->value;
|
||||
|
||||
if (uwsgi_stats_key(us, um->name)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_object_open(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keylong(us, "type", (long long) um->type)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "oid", um->oid ? um->oid : "")) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_keyslong(us, "value", (long long) um_val)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_object_close(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
|
||||
um = um->next;
|
||||
if (um) {
|
||||
if (uwsgi_stats_comma(us)) {
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
|
||||
if (uwsgi_stats_object_close(us))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_comma(us))
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (uwsgi_stats_key(us, "sockets"))
|
||||
goto end;
|
||||
|
||||
@@ -1345,7 +1415,7 @@ end:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void uwsgi_register_cheaper_algo(char *name, int (*func) (void)) {
|
||||
void uwsgi_register_cheaper_algo(char *name, int (*func) (int)) {
|
||||
|
||||
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
|
||||
|
||||
|
||||
+970
-63
File diff suppressed because it is too large
Load Diff
+19
-3
@@ -16,6 +16,7 @@
|
||||
#ifndef MS_REC
|
||||
#define MS_REC 16384
|
||||
#endif
|
||||
#include <sys/statfs.h>
|
||||
#endif
|
||||
|
||||
struct uwsgi_mount_flag {
|
||||
@@ -102,7 +103,7 @@ uint64_t uwsgi_mount_flag(char *mflag) {
|
||||
}
|
||||
|
||||
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
|
||||
#ifdef __FreeBSD__
|
||||
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
struct iovec iov[6];
|
||||
#endif
|
||||
unsigned long mountflags = 0;
|
||||
@@ -121,7 +122,7 @@ int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
|
||||
parsed:
|
||||
#ifdef __linux__
|
||||
return mount(what, where, fs, mountflags, NULL);
|
||||
#elif defined(__FreeBSD__)
|
||||
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
iov[0].iov_base = "fstype";
|
||||
iov[0].iov_len = 7;
|
||||
iov[1].iov_base = fs;
|
||||
@@ -189,7 +190,7 @@ unmountable:
|
||||
free(slashed);
|
||||
}
|
||||
return umount2(where, mountflags);
|
||||
#elif defined(__FreeBSD__)
|
||||
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
return unmount(where, mountflags);
|
||||
#endif
|
||||
return -1;
|
||||
@@ -236,3 +237,18 @@ int uwsgi_umount_hook(char *arg) {
|
||||
free(tmp_arg);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_check_mountpoint(char *mountpoint) {
|
||||
#ifdef __linux__
|
||||
struct statfs sfs;
|
||||
int ret = statfs(mountpoint, &sfs);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_check_mountpoint()/statfs()");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
#else
|
||||
uwsgi_log("this platform does not support mountpoints check !!!\n");
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
+1
-1
@@ -323,7 +323,7 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
|
||||
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
|
||||
return 0;
|
||||
}
|
||||
#if defined(__linux__) || defined(__sun__)
|
||||
#if defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
|
||||
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
|
||||
if (len > 0) {
|
||||
uor->written += len;
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@ void uwsgi_init_queue() {
|
||||
uwsgi.queue_header->pos = 0;
|
||||
uwsgi.queue_header->pull_pos = 0;
|
||||
}
|
||||
if (!uwsgi.queue) {
|
||||
if (uwsgi.queue == MAP_FAILED) {
|
||||
uwsgi_error("mmap()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -389,6 +389,8 @@ wait:
|
||||
remains -= len;
|
||||
*rlen += len;
|
||||
continue;
|
||||
}else if (len < 0 && (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS)) {
|
||||
goto wait;
|
||||
}
|
||||
*rlen = -1;
|
||||
if (len == 0) {
|
||||
|
||||
+100
-49
@@ -582,6 +582,88 @@ static int uwsgi_router_break(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// simple math router
|
||||
static int uwsgi_router_simple_math_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
uint16_t var_vallen = 0;
|
||||
char *var_value = uwsgi_get_var(wsgi_req, ur->data, ur->data_len, &var_vallen);
|
||||
if (!var_value) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
int64_t base_value = uwsgi_str_num(var_value, var_vallen);
|
||||
int64_t value = 1;
|
||||
|
||||
if (ur->data2_len) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data2, ur->data2_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
value = uwsgi_str_num(ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
|
||||
char out[sizeof(UMAX64_STR)+1];
|
||||
int64_t total = 0;
|
||||
|
||||
switch(ur->custom) {
|
||||
// -
|
||||
case 1:
|
||||
total = base_value - value;
|
||||
break;
|
||||
// *
|
||||
case 2:
|
||||
total = base_value * value;
|
||||
break;
|
||||
// /
|
||||
case 3:
|
||||
if (value == 0) total = 0;
|
||||
else {
|
||||
total = base_value/value;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
total = base_value + value;
|
||||
break;
|
||||
}
|
||||
|
||||
int ret = uwsgi_long2str2n(total, out, sizeof(UMAX64_STR)+1);
|
||||
if (ret <= 0) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
if (!uwsgi_req_append(wsgi_req, ur->data, ur->data_len, out, ret)) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
|
||||
static int uwsgi_router_simple_math_plus(struct uwsgi_route *ur, char *arg) {
|
||||
ur->func = uwsgi_router_simple_math_func;
|
||||
char *comma = strchr(arg, ',');
|
||||
if (comma) {
|
||||
ur->data = arg;
|
||||
ur->data_len = comma - arg;
|
||||
ur->data2 = comma+1;
|
||||
ur->data2_len = strlen(ur->data);
|
||||
}
|
||||
else {
|
||||
ur->data = arg;
|
||||
ur->data_len = strlen(arg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_router_simple_math_minus(struct uwsgi_route *ur, char *arg) {
|
||||
ur->custom = 1;
|
||||
return uwsgi_router_simple_math_plus(ur, arg);
|
||||
}
|
||||
|
||||
static int uwsgi_router_simple_math_multiply(struct uwsgi_route *ur, char *arg) {
|
||||
ur->custom = 2;
|
||||
return uwsgi_router_simple_math_plus(ur, arg);
|
||||
}
|
||||
|
||||
static int uwsgi_router_simple_math_divide(struct uwsgi_route *ur, char *arg) {
|
||||
ur->custom = 2;
|
||||
return uwsgi_router_simple_math_plus(ur, arg);
|
||||
}
|
||||
|
||||
// harakiri router
|
||||
static int uwsgi_router_harakiri_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
@@ -640,7 +722,6 @@ static int uwsgi_router_fixcl(struct uwsgi_route *ur, char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// log route
|
||||
static int uwsgi_router_log_func(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
|
||||
@@ -1199,10 +1280,21 @@ static int uwsgi_router_alarm(struct uwsgi_route *ur, char *arg) {
|
||||
|
||||
// send route
|
||||
static int uwsgi_router_send_func(struct wsgi_request *wsgi_req, struct uwsgi_route *route) {
|
||||
uwsgi_response_write_body_do(wsgi_req, route->data, route->data_len);
|
||||
char **subject = (char **) (((char *)(wsgi_req))+route->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+route->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, route, *subject, *subject_len, route->data, route->data_len);
|
||||
if (!ub) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
if (route->custom) {
|
||||
uwsgi_response_write_body_do(wsgi_req, "\r\n", 2);
|
||||
if (uwsgi_buffer_append(ub, "\r\n", 2)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
}
|
||||
uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
}
|
||||
static int uwsgi_router_send(struct uwsgi_route *ur, char *arg) {
|
||||
@@ -1629,48 +1721,6 @@ static char *uwsgi_route_var_hex(struct wsgi_request *wsgi_req, char *key, uint1
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
// avoid crash
|
||||
if (!wsgi_req->var_cnt) return NULL;
|
||||
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
|
||||
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
|
||||
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
|
||||
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
|
||||
int i,j = 0;
|
||||
char *ptr = vars_buf;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
|
||||
names[j] = ptr;
|
||||
ptr += wsgi_req->hvec[i-1].iov_len;
|
||||
*ptr++=0;
|
||||
char *num = ptr;
|
||||
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
ptr += wsgi_req->hvec[i].iov_len;
|
||||
*ptr++=0;
|
||||
values[j] = strtod(num, NULL);
|
||||
j++;
|
||||
}
|
||||
|
||||
char *expr = ptr;
|
||||
memcpy(ptr, key, keylen); ptr += keylen;
|
||||
*ptr++=0;
|
||||
|
||||
void *e = evaluator_create(expr);
|
||||
if (!e) goto end;
|
||||
double n = evaluator_evaluate(e, j, names, values);
|
||||
evaluator_destroy(e);
|
||||
ret = uwsgi_num2str((int)n);
|
||||
*vallen = strlen(ret);
|
||||
end:
|
||||
free(vars_buf);
|
||||
free(names);
|
||||
free(values);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
// register embedded routers
|
||||
void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("continue", uwsgi_router_continue);
|
||||
@@ -1703,6 +1753,11 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_router("setprocname", uwsgi_router_setprocname);
|
||||
uwsgi_register_router("alarm", uwsgi_router_alarm);
|
||||
|
||||
uwsgi_register_router("+", uwsgi_router_simple_math_plus);
|
||||
uwsgi_register_router("-", uwsgi_router_simple_math_minus);
|
||||
uwsgi_register_router("*", uwsgi_router_simple_math_multiply);
|
||||
uwsgi_register_router("/", uwsgi_router_simple_math_divide);
|
||||
|
||||
uwsgi_register_router("flush", uwsgi_router_flush);
|
||||
uwsgi_register_router("fixcl", uwsgi_router_fixcl);
|
||||
|
||||
@@ -1746,10 +1801,6 @@ void uwsgi_register_embedded_routers() {
|
||||
urv->need_free = 1;
|
||||
urv = uwsgi_register_route_var("httptime", uwsgi_route_var_httptime);
|
||||
urv->need_free = 1;
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
|
||||
urv->need_free = 1;
|
||||
#endif
|
||||
urv = uwsgi_register_route_var("base64", uwsgi_route_var_base64);
|
||||
urv->need_free = 1;
|
||||
|
||||
|
||||
+36
-8
@@ -59,11 +59,11 @@ already:
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
|
||||
uint64_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char **output) {
|
||||
|
||||
struct uwsgi_rpc *urpc = NULL;
|
||||
uint64_t i;
|
||||
uint16_t ret = 0;
|
||||
uint64_t ret = 0;
|
||||
|
||||
int pos = (uwsgi.mywid * uwsgi.rpc_max);
|
||||
|
||||
@@ -85,8 +85,15 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], cha
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rpc_context_hook(char *key, uint16_t kl, char *value, uint16_t vl, void *data) {
|
||||
size_t *r = (size_t *) data;
|
||||
|
||||
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t * len) {
|
||||
if (!uwsgi_strncmp(key, kl, "CONTENT_LENGTH", 14)) {
|
||||
*r = uwsgi_str_num(value, vl);
|
||||
}
|
||||
}
|
||||
|
||||
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint64_t * len) {
|
||||
|
||||
uint8_t i;
|
||||
uint16_t ulen;
|
||||
@@ -97,9 +104,10 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
|
||||
if (node == NULL || !strcmp(node, "")) {
|
||||
// allocate the whole buffer
|
||||
buffer = uwsgi_malloc(UMAX16);
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
|
||||
return buffer;
|
||||
*len = uwsgi_rpc(func, argc, argv, argvs, &buffer);
|
||||
if (*buffer)
|
||||
return buffer;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -147,17 +155,37 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
|
||||
bufptr += ulen;
|
||||
}
|
||||
|
||||
// ok the reuqest is ready, let's send it in non blocking way
|
||||
// ok the request is ready, let's send it in non blocking way
|
||||
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// ok time to wait for the response in non blocking way
|
||||
size_t rlen = buffer_size+4;
|
||||
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
uint8_t modifier2 = 0;
|
||||
if (uwsgi_read_with_realloc(fd, &buffer, &rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], NULL, &modifier2)) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// 64bit response ?
|
||||
if (modifier2 == 5) {
|
||||
size_t content_len = 0;
|
||||
if (uwsgi_hooked_parse(buffer, rlen, rpc_context_hook, &content_len )) goto error;
|
||||
|
||||
if (content_len > rlen) {
|
||||
char *tmp_buf = realloc(buffer, content_len);
|
||||
if (!tmp_buf) goto error;
|
||||
buffer = tmp_buf;
|
||||
}
|
||||
|
||||
rlen = content_len;
|
||||
|
||||
// read the raw value from the socket
|
||||
if (uwsgi_read_whole_true_nb(fd, buffer, rlen, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
close(fd);
|
||||
*len = rlen;
|
||||
if (*len == 0) {
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
|
||||
int sf_ret = sendfile(filefd, sockfd, pos, &sf_len, NULL, 0);
|
||||
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
|
||||
return -1;
|
||||
#elif defined(__linux__) || defined(__sun__)
|
||||
#elif defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
|
||||
off_t off = pos;
|
||||
return sendfile(sockfd, filefd, &off, len);
|
||||
#endif
|
||||
|
||||
@@ -301,8 +301,10 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
|
||||
else {
|
||||
uwsgi_error("uwsgi_signal_send()");
|
||||
}
|
||||
uwsgi.shared->unrouted_signals++;
|
||||
return -1;
|
||||
}
|
||||
uwsgi.shared->routed_signals++;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
+55
-14
@@ -23,6 +23,7 @@ static uint64_t get_uwsgi_custom_snmp_value(uint64_t, uint8_t *);
|
||||
static uint8_t snmp_int_to_snmp(uint64_t, uint8_t, uint8_t *);
|
||||
|
||||
static ssize_t build_snmp_response(uint8_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
|
||||
static ssize_t build_snmp_metric_response(int64_t, uint8_t, uint8_t *, int, uint8_t *, uint8_t *, uint8_t *);
|
||||
|
||||
void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_addr) {
|
||||
|
||||
@@ -71,7 +72,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
uwsgi_debug("SNMP version: %d\n", version);
|
||||
#endif
|
||||
|
||||
// check for community string (this must be set from the python vm using uwsgi.snmp_community or with --snmp-community arg)
|
||||
// check for community string (this must be set from the api using uwsgi.snmp_community or with --snmp-community arg)
|
||||
if (*ptr != SNMP_STRING)
|
||||
return;
|
||||
ptr++;
|
||||
@@ -196,7 +197,7 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
ptr++;
|
||||
|
||||
oidlen = *ptr;
|
||||
if (oidlen != 11)
|
||||
if (oidlen < 11)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
@@ -208,21 +209,33 @@ void manage_snmp(int fd, uint8_t * buffer, int size, struct sockaddr_in *client_
|
||||
|
||||
oid_part[0] = *ptr;
|
||||
|
||||
if (oid_part[0] != 1 && oid_part[0] != 2)
|
||||
return;
|
||||
ptr++;
|
||||
// old-style SNMP metrics
|
||||
if (oid_part[0] == 1 || oid_part[0] == 2) {
|
||||
ptr++;
|
||||
|
||||
oid_part[1] = *ptr;
|
||||
if (oid_part[1] < 1 || oid_part[1] > 100)
|
||||
return;
|
||||
ptr++;
|
||||
oid_part[1] = *ptr;
|
||||
if (oid_part[1] < 1 || oid_part[1] > 100)
|
||||
return;
|
||||
ptr++;
|
||||
|
||||
// check for null
|
||||
if (memcmp((char *) ptr, "\x05\x00", 2))
|
||||
return;
|
||||
ptr += 2;
|
||||
// check for null
|
||||
if (memcmp((char *) ptr, "\x05\x00", 2))
|
||||
return;
|
||||
ptr += 2;
|
||||
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
|
||||
}
|
||||
// metrics subsystem
|
||||
else {
|
||||
size_t metric_asn_len = oidlen - 9;
|
||||
char *metric_asn = (char *) ptr;
|
||||
struct uwsgi_metric *um = uwsgi_metric_find_by_asn(metric_asn, metric_asn_len);
|
||||
if (!um) return;
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
int64_t value = *um->value;
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
size = build_snmp_metric_response(value, um->type, buffer, size, seq1, seq2, seq3);
|
||||
}
|
||||
|
||||
size = build_snmp_response(oid_part[0], oid_part[1], buffer, size, seq1, seq2, seq3);
|
||||
|
||||
if (size > 0) {
|
||||
if (sendto(fd, buffer, size, 0, (struct sockaddr *) client_addr, sizeof(struct sockaddr_in)) < 0) {
|
||||
@@ -292,6 +305,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
|
||||
uint8_t tlen;
|
||||
int i, j;
|
||||
uint8_t *ptr = (uint8_t *) & snmp_val;
|
||||
int32_t val32 = (int32_t) snmp_val;
|
||||
|
||||
// check for counter, counter64 or gauge
|
||||
|
||||
@@ -303,6 +317,7 @@ static uint8_t snmp_int_to_snmp(uint64_t snmp_val, uint8_t oid_type, uint8_t * b
|
||||
}
|
||||
else {
|
||||
tlen = 4;
|
||||
ptr = (uint8_t *) &val32;
|
||||
}
|
||||
|
||||
buffer[0] = tlen;
|
||||
@@ -352,6 +367,32 @@ static ssize_t build_snmp_response(uint8_t oid1, uint8_t oid2, uint8_t * buffer,
|
||||
|
||||
}
|
||||
|
||||
static ssize_t build_snmp_metric_response(int64_t value, uint8_t type, uint8_t * buffer, int size, uint8_t * seq1, uint8_t * seq2, uint8_t * seq3) {
|
||||
uint8_t oid_sz;
|
||||
|
||||
if (type == UWSGI_METRIC_GAUGE) {
|
||||
buffer[size - 2] = SNMP_GAUGE;
|
||||
oid_sz = snmp_int_to_snmp(value, SNMP_GAUGE, buffer + (size - 1));
|
||||
}
|
||||
else {
|
||||
buffer[size - 2] = SNMP_COUNTER64;
|
||||
oid_sz = snmp_int_to_snmp(value, SNMP_COUNTER64, buffer + (size - 1));
|
||||
}
|
||||
|
||||
if (oid_sz < 1)
|
||||
return -1;
|
||||
|
||||
oid_sz--;
|
||||
|
||||
buffer[1] += oid_sz;
|
||||
*seq1 += oid_sz;
|
||||
*seq2 += oid_sz;
|
||||
*seq3 += oid_sz;
|
||||
|
||||
return size + oid_sz;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_snmp(char *opt, char *value, void *foobar) {
|
||||
uwsgi.snmp = 1;
|
||||
if (value) {
|
||||
|
||||
+64
-103
@@ -6,6 +6,22 @@ static int connect_to_unix(char *, int, int);
|
||||
static int connect_to_tcp(char *, int, int, int);
|
||||
static int connect_to_udp(char *, int);
|
||||
|
||||
void uwsgi_socket_setup_protocol(struct uwsgi_socket *uwsgi_sock, char *protocol) {
|
||||
if (!protocol) protocol = "uwsgi";
|
||||
struct uwsgi_protocol *up = uwsgi.protocols;
|
||||
while(up) {
|
||||
if (!strcmp(protocol, up->name)) {
|
||||
up->func(uwsgi_sock);
|
||||
return;
|
||||
}
|
||||
up = up->next;
|
||||
}
|
||||
|
||||
uwsgi_log("unable to find protocol %s\n", protocol);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
|
||||
size_t sock1_len = strlen(sock1);
|
||||
size_t sock2_len = strlen(sock2);
|
||||
@@ -1366,7 +1382,7 @@ void uwsgi_add_sockets_to_queue(int queue, int async_id) {
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (uwsgi_sock->fd_threads && async_id > -1) {
|
||||
if (uwsgi_sock->fd_threads && async_id > -1 && uwsgi_sock->fd_threads[async_id] > -1) {
|
||||
event_queue_add_fd_read(queue, uwsgi_sock->fd_threads[async_id]);
|
||||
}
|
||||
else if (uwsgi_sock->fd > -1) {
|
||||
@@ -1673,18 +1689,7 @@ void uwsgi_map_sockets() {
|
||||
|
||||
if (!enabled) {
|
||||
close(uwsgi_sock->fd);
|
||||
int fd = open("/dev/null", O_RDONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
if (fd != uwsgi_sock->fd) {
|
||||
if (dup2(fd, uwsgi_sock->fd) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
uwsgi_remap_fd(uwsgi_sock->fd, "/dev/null");
|
||||
uwsgi_sock->disabled = 1;
|
||||
}
|
||||
|
||||
@@ -1714,6 +1719,10 @@ void uwsgi_bind_sockets() {
|
||||
while (uwsgi_sock) {
|
||||
if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
|
||||
char *tcp_port = strrchr(uwsgi_sock->name, ':');
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
if (uwsgi_sock->no_defer) {
|
||||
uwsgi.no_defer_accept = 1;
|
||||
}
|
||||
if (tcp_port == NULL) {
|
||||
uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
uwsgi_sock->family = AF_UNIX;
|
||||
@@ -1747,6 +1756,7 @@ void uwsgi_bind_sockets() {
|
||||
uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
@@ -1859,96 +1869,8 @@ void uwsgi_set_sockets_protocols() {
|
||||
|
||||
|
||||
setup_proto:
|
||||
if (!requested_protocol) {
|
||||
requested_protocol = uwsgi.protocol;
|
||||
}
|
||||
|
||||
if (requested_protocol && !strcmp("http", requested_protocol)) {
|
||||
uwsgi_sock->proto = uwsgi_proto_http_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.offload_threads > 0)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("scgi", requested_protocol) || !strcmp("scgi", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
|
||||
else if (requested_protocol && (!strcmp("scgi-nph", requested_protocol) || !strcmp("scgi-nph", requested_protocol))) {
|
||||
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
|
||||
uwsgi.zeromq = 1;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
if (uwsgi.offload_threads > 0)
|
||||
uwsgi_sock->can_offload = 1;
|
||||
}
|
||||
if (!requested_protocol) requested_protocol = uwsgi.protocol;
|
||||
uwsgi_socket_setup_protocol(uwsgi_sock, requested_protocol);
|
||||
nextsock:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
@@ -1984,3 +1906,42 @@ int uwsgi_accept(int server_fd) {
|
||||
|
||||
}
|
||||
|
||||
struct uwsgi_protocol *uwsgi_register_protocol(char *name, void (*func)(struct uwsgi_socket *)) {
|
||||
struct uwsgi_protocol *old_up = NULL, *up = uwsgi.protocols;
|
||||
while(up) {
|
||||
if (!strcmp(name, up->name)) {
|
||||
goto found;
|
||||
}
|
||||
old_up = up;
|
||||
up = up->next;
|
||||
}
|
||||
up = uwsgi_calloc(sizeof(struct uwsgi_protocol));
|
||||
up->name = name;
|
||||
if (old_up) {
|
||||
old_up->next = up;
|
||||
}
|
||||
else {
|
||||
uwsgi.protocols = up;
|
||||
}
|
||||
found:
|
||||
up->func = func;
|
||||
return up;
|
||||
}
|
||||
|
||||
void uwsgi_protocols_register() {
|
||||
uwsgi_register_protocol("uwsgi", uwsgi_proto_uwsgi_setup);
|
||||
uwsgi_register_protocol("puwsgi", uwsgi_proto_puwsgi_setup);
|
||||
uwsgi_register_protocol("http", uwsgi_proto_http_setup);
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_register_protocol("suwsgi", uwsgi_proto_suwsgi_setup);
|
||||
uwsgi_register_protocol("https", uwsgi_proto_https_setup);
|
||||
#endif
|
||||
uwsgi_register_protocol("fastcgi", uwsgi_proto_fastcgi_setup);
|
||||
uwsgi_register_protocol("fastcgi-nph", uwsgi_proto_fastcgi_nph_setup);
|
||||
uwsgi_register_protocol("scgi", uwsgi_proto_scgi_setup);
|
||||
uwsgi_register_protocol("scgi-nph", uwsgi_proto_scgi_nph_setup);
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
uwsgi_register_protocol("zmq", uwsgi_proto_zmq_setup);
|
||||
#endif
|
||||
uwsgi_register_protocol("raw", uwsgi_proto_raw_setup);
|
||||
}
|
||||
|
||||
+18
-45
@@ -440,6 +440,11 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
void *events = event_queue_alloc(1);
|
||||
for (;;) {
|
||||
int nevents = event_queue_wait_multi(ut->queue, 1, events, 1);
|
||||
if (nevents < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
uwsgi_log_verbose("ending the stats pusher thread...\n");
|
||||
return;
|
||||
}
|
||||
if (nevents > 0) {
|
||||
int interesting_fd = event_queue_interesting_fd(events, 0);
|
||||
char buf[4096];
|
||||
@@ -457,7 +462,8 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
struct uwsgi_stats *us = NULL;
|
||||
while (uspi) {
|
||||
int delta = uspi->freq ? uspi->freq : uwsgi.stats_pusher_default_freq;
|
||||
if ((uspi->last_run + delta) <= now) {
|
||||
if (((uspi->last_run + delta) <= now) || (uspi->needs_retry && (uspi->next_retry <= now))) {
|
||||
if (uspi->needs_retry) uspi->retries++;
|
||||
if (uspi->raw) {
|
||||
uspi->pusher->func(uspi, now, NULL, 0);
|
||||
}
|
||||
@@ -470,6 +476,17 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
|
||||
uspi->pusher->func(uspi, now, us->base, us->pos);
|
||||
}
|
||||
uspi->last_run = now;
|
||||
if (uspi->needs_retry && uspi->max_retries > 0 && uspi->retries < uspi->max_retries) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] %s failed (%d), retry in %ds\n", uspi->pusher->name, uspi->retries, uspi->retry_delay);
|
||||
uspi->next_retry = now + uspi->retry_delay;
|
||||
} else if (uspi->needs_retry && uspi->retries >= uspi->max_retries) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] %s failed and maximum number of retries was reached (%d)\n", uspi->pusher->name, uspi->retries);
|
||||
uspi->needs_retry = 0;
|
||||
uspi->retries = 0;
|
||||
} else if (uspi->retries) {
|
||||
uwsgi_log("[uwsgi-stats-pusher] retry succeeded for %s\n", uspi->pusher->name);
|
||||
uspi->retries = 0;
|
||||
}
|
||||
}
|
||||
next:
|
||||
uspi = uspi->next;
|
||||
@@ -531,50 +548,6 @@ struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func)
|
||||
return pusher;
|
||||
}
|
||||
|
||||
struct uwsgi_stats_pusher_file_conf {
|
||||
char *path;
|
||||
char *freq;
|
||||
char *separator;
|
||||
};
|
||||
|
||||
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
|
||||
struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
|
||||
if (!uspi->configured) {
|
||||
uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
|
||||
if (uspi->arg) {
|
||||
if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=', "path", &uspic->path, "separator", &uspic->separator, "freq", &uspic->freq, NULL)) {
|
||||
free(uspi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!uspic->path)
|
||||
uspic->path = "uwsgi.stats";
|
||||
if (!uspic->separator)
|
||||
uspic->separator = "\n\n";
|
||||
if (uspic->freq)
|
||||
uspi->freq = atoi(uspic->freq);
|
||||
uspi->configured = 1;
|
||||
uspi->data = uspic;
|
||||
}
|
||||
|
||||
int fd = open(uspic->path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(uspic->path);
|
||||
return;
|
||||
}
|
||||
ssize_t rlen = write(fd, json, json_len);
|
||||
if (rlen != (ssize_t) json_len) {
|
||||
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
|
||||
}
|
||||
|
||||
rlen = write(fd, uspic->separator, strlen(uspic->separator));
|
||||
if (rlen != (ssize_t) strlen(uspic->separator)) {
|
||||
uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
|
||||
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
|
||||
if (us->dirty) return;
|
||||
|
||||
+104
@@ -379,3 +379,107 @@ char *uwsgi_cheap_string(char *buf, int len) {
|
||||
return buf - 1;
|
||||
}
|
||||
|
||||
/*
|
||||
status 0: append mode
|
||||
status 1: single quote found
|
||||
status 2: double quote found
|
||||
status 3: backslash found (on 0)
|
||||
status 4: backslash found (on 1)
|
||||
status 5: backslash found (on 2)
|
||||
|
||||
*/
|
||||
char ** uwsgi_split_quoted(char *what, size_t what_len, char *sep, size_t *rlen) {
|
||||
size_t i;
|
||||
int status = 0;
|
||||
char *base = uwsgi_concat2n(what, what_len, "", 0);
|
||||
char *item = NULL;
|
||||
char *ptr = NULL;
|
||||
*rlen = 0;
|
||||
char **ret = (char **) uwsgi_malloc(sizeof(char *) * (what_len+1));
|
||||
|
||||
for(i=0;i<what_len;i++) {
|
||||
if (!item) {
|
||||
item = uwsgi_malloc((what_len - i)+1);
|
||||
ptr = item;
|
||||
}
|
||||
|
||||
if (status == 0) {
|
||||
if (base[i] == '\\') {
|
||||
status = 3;
|
||||
}
|
||||
else if (base[i] == '"') {
|
||||
status = 2;
|
||||
}
|
||||
else if (base[i] == '\'') {
|
||||
status = 1;
|
||||
}
|
||||
else if (strchr(sep, base[i])) {
|
||||
*ptr++= 0;
|
||||
ret[(*rlen)] = item; (*rlen)++;
|
||||
item = NULL;
|
||||
}
|
||||
else {
|
||||
*ptr++= base[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// backslash
|
||||
if (status == 3) {
|
||||
*ptr++= base[i];
|
||||
status = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
// single quote
|
||||
if (status == 1) {
|
||||
if (base[i] == '\\') {
|
||||
status = 4;
|
||||
}
|
||||
else if (base[i] == '\'') {
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
*ptr++= base[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// double quote
|
||||
if (status == 2) {
|
||||
if (base[i] == '\\') {
|
||||
status = 5;
|
||||
}
|
||||
else if (base[i] == '"') {
|
||||
status = 0;
|
||||
}
|
||||
else {
|
||||
*ptr++= base[i];
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// backslash single quote
|
||||
if (status == 4) {
|
||||
*ptr++= base[i];
|
||||
status = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// backslash double quote
|
||||
if (status == 5) {
|
||||
*ptr++= base[i];
|
||||
status = 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (item) {
|
||||
*ptr++= 0;
|
||||
ret[(*rlen)] = item; (*rlen)++;
|
||||
}
|
||||
|
||||
free(base);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
+1097
-919
File diff suppressed because it is too large
Load Diff
+291
-261
@@ -38,11 +38,21 @@ UWSGI_DECLARE_EMBEDDED_PLUGINS;
|
||||
static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"socket", required_argument, 's', "bind to the specified UNIX/TCP socket using default protocol", uwsgi_opt_add_socket, NULL, 0},
|
||||
{"uwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol", uwsgi_opt_add_socket, "uwsgi", 0},
|
||||
#ifdef UWSGI_SSL
|
||||
{"suwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
{"ssl-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol over SSL", uwsgi_opt_add_ssl_socket, "suwsgi", 0},
|
||||
#endif
|
||||
|
||||
{"http-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTP protocol", uwsgi_opt_add_socket, "http", 0},
|
||||
{"http-socket-modifier1", required_argument, 0, "force the specified modifier1 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier1, 0},
|
||||
{"http-socket-modifier2", required_argument, 0, "force the specified modifier2 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier2, 0},
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
{"https-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTPS protocol", uwsgi_opt_add_ssl_socket, "https", 0},
|
||||
{"https-socket-modifier1", required_argument, 0, "force the specified modifier1 when using HTTPS protocol", uwsgi_opt_set_64bit, &uwsgi.https_modifier1, 0},
|
||||
{"https-socket-modifier2", required_argument, 0, "force the specified modifier2 when using HTTPS protocol", uwsgi_opt_set_64bit, &uwsgi.https_modifier2, 0},
|
||||
#endif
|
||||
|
||||
{"fastcgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using FastCGI protocol", uwsgi_opt_add_socket, "fastcgi", 0},
|
||||
{"fastcgi-nph-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using FastCGI protocol (nph mode)", uwsgi_opt_add_socket, "fastcgi-nph", 0},
|
||||
{"fastcgi-modifier1", required_argument, 0, "force the specified modifier1 when using FastCGI protocol", uwsgi_opt_set_64bit, &uwsgi.fastcgi_modifier1, 0},
|
||||
@@ -53,6 +63,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"scgi-modifier1", required_argument, 0, "force the specified modifier1 when using SCGI protocol", uwsgi_opt_set_64bit, &uwsgi.scgi_modifier1, 0},
|
||||
{"scgi-modifier2", required_argument, 0, "force the specified modifier2 when using SCGI protocol", uwsgi_opt_set_64bit, &uwsgi.scgi_modifier2, 0},
|
||||
|
||||
{"raw-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using RAW protocol", uwsgi_opt_add_socket_no_defer, "raw", 0},
|
||||
{"raw-modifier1", required_argument, 0, "force the specified modifier1 when using RAW protocol", uwsgi_opt_set_64bit, &uwsgi.raw_modifier1, 0},
|
||||
{"raw-modifier2", required_argument, 0, "force the specified modifier2 when using RAW protocol", uwsgi_opt_set_64bit, &uwsgi.raw_modifier2, 0},
|
||||
|
||||
{"puwsgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using persistent uwsgi protocol (puwsgi)", uwsgi_opt_add_socket, "puwsgi", 0},
|
||||
|
||||
{"protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
|
||||
{"socket-protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
|
||||
{"shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc", uwsgi_opt_add_shared_socket, NULL, 0},
|
||||
@@ -78,7 +94,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero, 0},
|
||||
{"skip-atexit", no_argument, 0, "skip atexit hooks (ignored by the master)", uwsgi_opt_true, &uwsgi.skip_atexit, 0},
|
||||
|
||||
{"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"set", required_argument, 'S', "set a placeholder or an option", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"set-placeholder", required_argument, 0, "set a placeholder", uwsgi_opt_set_placeholder, (void *) 1, UWSGI_OPT_IMMEDIATE},
|
||||
{"set-ph", required_argument, 0, "set a placeholder", uwsgi_opt_set_placeholder, (void *) 1, UWSGI_OPT_IMMEDIATE},
|
||||
{"get", required_argument, 0, "print the specified option value and exit", uwsgi_opt_add_string_list, &uwsgi.get_list, UWSGI_OPT_NO_INITIAL},
|
||||
{"declare-option", required_argument, 0, "declare a new uWSGI custom option", uwsgi_opt_add_custom_option, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
@@ -173,10 +191,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
|
||||
{"honour-stdin", no_argument, 0, "do not remap stdin to /dev/null", uwsgi_opt_true, &uwsgi.honour_stdin, 0},
|
||||
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
|
||||
{"emperor-proxy-socket", required_argument, 0, "force the vassal to became an Emperor proxy", uwsgi_opt_set_str, &uwsgi.emperor_proxy, 0},
|
||||
{"emperor-wrapper", required_argument, 0, "set a binary wrapper for vassals", uwsgi_opt_set_str, &uwsgi.emperor_wrapper, 0},
|
||||
{"emperor-nofollow", no_argument, 0, "do not follow symlinks when checking for mtime", uwsgi_opt_true, &uwsgi.emperor_nofollow, 0},
|
||||
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
|
||||
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
|
||||
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
|
||||
{"emperor-curse-tolerance", required_argument, 0, "set the Emperor tolerance about cursed vassals", uwsgi_opt_set_int, &uwsgi.emperor_curse_tolerance, 0},
|
||||
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
|
||||
{"emperor-tyrant", no_argument, 0, "put the Emperor in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant, 0},
|
||||
{"emperor-tyrant-nofollow", no_argument, 0, "do not follow symlinks when checking for uid/gid in Tyrant mode", uwsgi_opt_true, &uwsgi.emperor_tyrant_nofollow, 0},
|
||||
@@ -196,21 +217,31 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-extra-ext", required_argument, 0, "allows the specified extension in the Emperor (vassal will be called with --config)", uwsgi_opt_add_string_list, &uwsgi.emperor_extra_extension, 0},
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
{"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0},
|
||||
#endif
|
||||
#ifdef UWSGI_CAP
|
||||
{"emperor-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0},
|
||||
{"vassals-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0},
|
||||
{"vassal-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0},
|
||||
#endif
|
||||
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config (uses --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
{"vassals-include", required_argument, 0, "include config templates to vassals config (uses --include instead of --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_includes, 0},
|
||||
{"vassals-inherit-before", required_argument, 0, "add config templates to vassals config (uses --inherit, parses before the vassal file)", uwsgi_opt_add_string_list, &uwsgi.vassals_templates_before, 0},
|
||||
{"vassals-include-before", required_argument, 0, "include config templates to vassals config (uses --include instead of --inherit, parses before the vassal file)", uwsgi_opt_add_string_list, &uwsgi.vassals_includes_before, 0},
|
||||
{"vassals-start-hook", required_argument, 0, "run the specified command before each vassal starts", uwsgi_opt_set_str, &uwsgi.vassals_start_hook, 0},
|
||||
{"vassals-stop-hook", required_argument, 0, "run the specified command after vassal's death", uwsgi_opt_set_str, &uwsgi.vassals_stop_hook, 0},
|
||||
{"vassal-sos-backlog", required_argument, 0, "ask emperor for sos if backlog queue has more items than the value specified", uwsgi_opt_set_int, &uwsgi.vassal_sos_backlog, 0},
|
||||
{"heartbeat", required_argument, 0, "announce healtness to the emperor", uwsgi_opt_set_int, &uwsgi.heartbeat, 0},
|
||||
{"auto-snapshot", optional_argument, 0, "automatically make workers snaphost after reload", uwsgi_opt_set_int, &uwsgi.auto_snapshot, UWSGI_OPT_LAZY},
|
||||
{"vassals-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
|
||||
{"vassal-set", required_argument, 0, "automatically set the specified option (via --set) for every vassal", uwsgi_opt_add_string_list, &uwsgi.vassals_set, 0},
|
||||
|
||||
{"heartbeat", required_argument, 0, "announce healthiness to the emperor", uwsgi_opt_set_int, &uwsgi.heartbeat, 0},
|
||||
|
||||
{"reload-mercy", required_argument, 0, "set the maximum time (in seconds) we wait for workers and other processes to die during reload/shutdown", uwsgi_opt_set_int, &uwsgi.reload_mercy, 0},
|
||||
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
|
||||
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
|
||||
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
|
||||
{"force-gateway", no_argument, 0, "force teh spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
|
||||
{"force-gateway", no_argument, 0, "force the spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
|
||||
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
@@ -277,6 +308,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"signal-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
|
||||
{"signals-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
|
||||
|
||||
{"signal-timer", required_argument, 0, "add a timer (syntax: <signal> <seconds>)", uwsgi_opt_add_string_list, &uwsgi.signal_timers, UWSGI_OPT_MASTER},
|
||||
{"timer", required_argument, 0, "add a timer (syntax: <signal> <seconds>)", uwsgi_opt_add_string_list, &uwsgi.signal_timers, UWSGI_OPT_MASTER},
|
||||
|
||||
{"signal-rbtimer", required_argument, 0, "add a redblack timer (syntax: <signal> <seconds>)", uwsgi_opt_add_string_list, &uwsgi.rb_signal_timers, UWSGI_OPT_MASTER},
|
||||
{"rbtimer", required_argument, 0, "add a redblack timer (syntax: <signal> <seconds>)", uwsgi_opt_add_string_list, &uwsgi.rb_signal_timers, UWSGI_OPT_MASTER},
|
||||
|
||||
{"rpc-max", required_argument, 0, "maximum number of rpc slots (default: 64)", uwsgi_opt_set_64bit, &uwsgi.rpc_max, 0},
|
||||
|
||||
{"disable-logging", no_argument, 'L', "disable request logging", uwsgi_opt_dyn_false, (void *) UWSGI_OPTION_LOGGING, 0},
|
||||
@@ -306,8 +343,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
{"unshare", required_argument, 0, "unshare() part of the processes and put it in a new namespace", uwsgi_opt_set_unshare, &uwsgi.unshare, 0},
|
||||
{"unshare2", required_argument, 0, "unshare() part of the processes and put it in a new namespace after rootfs change", uwsgi_opt_set_unshare, &uwsgi.unshare2, 0},
|
||||
#endif
|
||||
#ifdef __FreeBSD__
|
||||
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
{"jail", required_argument, 0, "put the instance in a FreeBSD jail", uwsgi_opt_set_str, &uwsgi.jail, 0},
|
||||
{"jail-ip4", required_argument, 0, "add an ipv4 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip4, 0},
|
||||
{"jail-ip6", required_argument, 0, "add an ipv6 address to the FreeBSD jail", uwsgi_opt_add_string_list, &uwsgi.jail_ip6, 0},
|
||||
@@ -406,7 +444,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#ifdef UWSGI_YAML
|
||||
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"yal", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"yml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_JSON
|
||||
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -462,6 +500,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"fs-brutal-reload", required_argument, 0, "brutal reload when the specified filesystem object is modified", uwsgi_opt_add_string_list, &uwsgi.fs_brutal_reload, UWSGI_OPT_MASTER},
|
||||
{"fs-signal", required_argument, 0, "raise a uwsgi signal when the specified filesystem object is modified (syntax: file signal)", uwsgi_opt_add_string_list, &uwsgi.fs_signal, UWSGI_OPT_MASTER},
|
||||
|
||||
{"check-mountpoint", required_argument, 0, "destroy the instance if a filesystem is no more reachable (useful for reliable Fuse management)", uwsgi_opt_add_string_list, &uwsgi.mountpoints_check, UWSGI_OPT_MASTER},
|
||||
{"mountpoint-check", required_argument, 0, "destroy the instance if a filesystem is no more reachable (useful for reliable Fuse management)", uwsgi_opt_add_string_list, &uwsgi.mountpoints_check, UWSGI_OPT_MASTER},
|
||||
{"check-mount", required_argument, 0, "destroy the instance if a filesystem is no more reachable (useful for reliable Fuse management)", uwsgi_opt_add_string_list, &uwsgi.mountpoints_check, UWSGI_OPT_MASTER},
|
||||
{"mount-check", required_argument, 0, "destroy the instance if a filesystem is no more reachable (useful for reliable Fuse management)", uwsgi_opt_add_string_list, &uwsgi.mountpoints_check, UWSGI_OPT_MASTER},
|
||||
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal management", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
|
||||
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
|
||||
@@ -482,13 +525,22 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"reload-on-exception-repr", required_argument, 0, "reload a worker when a specific exception type+value (language-specific) is raised", uwsgi_opt_add_string_list, &uwsgi.reload_on_exception_repr, 0},
|
||||
{"exception-handler", required_argument, 0, "add an exception handler", uwsgi_opt_add_string_list, &uwsgi.exception_handlers_instance, UWSGI_OPT_MASTER},
|
||||
|
||||
{"enable-metrics", no_argument, 0, "enable metrics subsystem", uwsgi_opt_true, &uwsgi.has_metrics, UWSGI_OPT_MASTER},
|
||||
{"metric", required_argument, 0, "add a custom metric", uwsgi_opt_add_string_list, &uwsgi.additional_metrics, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-threshold", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-alarm", required_argument, 0, "add a metric threshold/alarm", uwsgi_opt_add_string_list, &uwsgi.metrics_threshold, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metrics-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metrics-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-dir", required_argument, 0, "export metrics as text files to the specified directory", uwsgi_opt_set_str, &uwsgi.metrics_dir, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
{"metric-dir-restore", no_argument, 0, "restore last value taken from the metrics dir", uwsgi_opt_true, &uwsgi.metrics_dir_restore, UWSGI_OPT_METRICS|UWSGI_OPT_MASTER},
|
||||
|
||||
{"udp", required_argument, 0, "run the udp server on the specified address", uwsgi_opt_set_str, &uwsgi.udp_socket, UWSGI_OPT_MASTER},
|
||||
{"stats", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
|
||||
{"stats-server", required_argument, 0, "enable the stats server on the specified address", uwsgi_opt_set_str, &uwsgi.stats, UWSGI_OPT_MASTER},
|
||||
{"stats-http", no_argument, 0, "prefix stats server json output with http headers", uwsgi_opt_true, &uwsgi.stats_http, UWSGI_OPT_MASTER},
|
||||
{"stats-minified", no_argument, 0, "minify statistics json output", uwsgi_opt_true, &uwsgi.stats_minified, UWSGI_OPT_MASTER},
|
||||
{"stats-min", no_argument, 0, "minify statistics json output", uwsgi_opt_true, &uwsgi.stats_minified, UWSGI_OPT_MASTER},
|
||||
{"stats-push", required_argument, 0, "push the stats json to the specified destination", uwsgi_opt_add_string_list, &uwsgi.requested_stats_pushers, UWSGI_OPT_MASTER},
|
||||
{"stats-push", required_argument, 0, "push the stats json to the specified destination", uwsgi_opt_add_string_list, &uwsgi.requested_stats_pushers, UWSGI_OPT_MASTER|UWSGI_OPT_METRICS},
|
||||
{"stats-pusher-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
{"stats-pushers-default-freq", required_argument, 0, "set the default frequency of stats pushers", uwsgi_opt_set_int, &uwsgi.stats_pusher_default_freq, UWSGI_OPT_MASTER},
|
||||
{"multicast", required_argument, 0, "subscribe to specified multicast group", uwsgi_opt_set_str, &uwsgi.multicast_group, UWSGI_OPT_MASTER},
|
||||
@@ -606,7 +658,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"log-master-req-stream", no_argument, 0, "create the master requests logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_req_stream, 0},
|
||||
{"log-reopen", no_argument, 0, "reopen log after reload", uwsgi_opt_true, &uwsgi.log_reopen, 0},
|
||||
{"log-truncate", no_argument, 0, "truncate log on startup", uwsgi_opt_true, &uwsgi.log_truncate, 0},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_int, &uwsgi.log_maxsize, UWSGI_OPT_LOG_MASTER},
|
||||
{"log-maxsize", required_argument, 0, "set maximum logfile size", uwsgi_opt_set_64bit, &uwsgi.log_maxsize, UWSGI_OPT_LOG_MASTER},
|
||||
{"log-backupname", required_argument, 0, "set logfile name after rotation", uwsgi_opt_set_str, &uwsgi.log_backupname, 0},
|
||||
|
||||
{"logdate", optional_argument, 0, "prefix logs with date or a strftime string", uwsgi_opt_log_date, NULL, 0},
|
||||
@@ -808,6 +860,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"namespace-net", required_argument, 0, "add network namespace", uwsgi_opt_set_str, &uwsgi.ns_net, 0},
|
||||
{"ns-net", required_argument, 0, "add network namespace", uwsgi_opt_set_str, &uwsgi.ns_net, 0},
|
||||
#endif
|
||||
{"enable-proxy-protocol", no_argument, 0, "enable PROXY1 protocol support (only for http parsers)", uwsgi_opt_true, &uwsgi.enable_proxy_protocol, 0},
|
||||
{"reuse-port", no_argument, 0, "enable REUSE_PORT flag on socket (BSD only)", uwsgi_opt_true, &uwsgi.reuse_port, 0},
|
||||
{"tcp-fast-open", required_argument, 0, "enable TCP_FASTOPEN flag on TCP sockets with the specified qlen value", uwsgi_opt_set_int, &uwsgi.tcp_fast_open, 0},
|
||||
{"tcp-fastopen", required_argument, 0, "enable TCP_FASTOPEN flag on TCP sockets with the specified qlen value", uwsgi_opt_set_int, &uwsgi.tcp_fast_open, 0},
|
||||
@@ -833,6 +886,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"worker-exec", required_argument, 0, "run the specified command as worker", uwsgi_opt_set_str, &uwsgi.worker_exec, 0},
|
||||
{"worker-exec2", required_argument, 0, "run the specified command as worker (after post_fork hook)", uwsgi_opt_set_str, &uwsgi.worker_exec2, 0},
|
||||
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"attach-control-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background), when the daemon dies, the master dies too", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_SSL
|
||||
@@ -856,7 +910,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"dump-options", no_argument, 0, "dump the full list of available options", uwsgi_opt_true, &uwsgi.dump_options, 0},
|
||||
{"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config, 0},
|
||||
{"binary-append-data", required_argument, 0, "return the content of a resource to stdout for appending to a uwsgi binary (for data:// usage)", uwsgi_opt_binary_append_data, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL, 0},
|
||||
{"iprint", required_argument, 0, "simple print (immediate version)", uwsgi_opt_print, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"exit", optional_argument, 0, "force exit() of the instance", uwsgi_opt_exit, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"cflags", no_argument, 0, "report uWSGI CFLAGS (useful for building external plugins)", uwsgi_opt_cflags, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"dot-h", no_argument, 0, "dump the uwsgi.h used for building the core (useful for building external plugins)", uwsgi_opt_dot_h, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
|
||||
@@ -878,140 +935,6 @@ void show_config(void) {
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_manage_custom_option(struct uwsgi_custom_option *uco, char *key, char *value) {
|
||||
int configured;
|
||||
size_t i, count = 1;
|
||||
size_t value_len = 0;
|
||||
if (value)
|
||||
value_len = strlen(value);
|
||||
off_t pos = 0;
|
||||
char **opt_argv;
|
||||
char *tmp_val = NULL, *p = NULL;
|
||||
|
||||
if (strcmp(uco->name, key)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// now count the number of args
|
||||
for (i = 0; i < value_len; i++) {
|
||||
if (value[i] == ' ') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate a tmp array
|
||||
opt_argv = uwsgi_calloc(sizeof(char *) * count);
|
||||
//make a copy of the value;
|
||||
if (value_len > 0) {
|
||||
tmp_val = uwsgi_str(value);
|
||||
// fill the array of options
|
||||
char *p, *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_val, " ", p, ctx) {
|
||||
opt_argv[pos] = p;
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// no argument specified
|
||||
opt_argv[0] = "";
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("found custom option %s with %d args\n", key, count);
|
||||
#endif
|
||||
|
||||
// now make a copy of the option template
|
||||
char *tmp_opt = uwsgi_str(uco->value);
|
||||
// split it
|
||||
char *ctx = NULL;
|
||||
uwsgi_foreach_token(tmp_opt, ";", p, ctx) {
|
||||
char *equal = strchr(p, '=');
|
||||
if (!equal)
|
||||
goto clear;
|
||||
*equal = '\0';
|
||||
|
||||
// build the key
|
||||
char *new_key = uwsgi_str(p);
|
||||
for (i = 0; i < count; i++) {
|
||||
char *old_key = new_key;
|
||||
char *tmp_num = uwsgi_num2str(i + 1);
|
||||
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
|
||||
free(tmp_num);
|
||||
new_key = uwsgi_substitute(old_key, placeholder, opt_argv[i]);
|
||||
if (new_key != old_key)
|
||||
free(old_key);
|
||||
free(placeholder);
|
||||
}
|
||||
|
||||
// build the value
|
||||
char *new_value = uwsgi_str(equal + 1);
|
||||
for (i = 0; i < count; i++) {
|
||||
char *old_value = new_value;
|
||||
char *tmp_num = uwsgi_num2str(i + 1);
|
||||
char *placeholder = uwsgi_concat2((char *) "$", tmp_num);
|
||||
free(tmp_num);
|
||||
new_value = uwsgi_substitute(old_value, placeholder, opt_argv[i]);
|
||||
if (new_value != old_value)
|
||||
free(old_value);
|
||||
free(placeholder);
|
||||
}
|
||||
retry:
|
||||
configured = uwsgi_manage_opt(new_key, new_value);
|
||||
if (!configured && uwsgi.autoload) {
|
||||
if (uwsgi_try_autoload(new_key)) goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
clear:
|
||||
free(tmp_val);
|
||||
free(tmp_opt);
|
||||
free(opt_argv);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_manage_opt(char *key, char *value) {
|
||||
|
||||
struct uwsgi_option *op = uwsgi.options;
|
||||
while (op->name) {
|
||||
if (!strcmp(key, op->name)) {
|
||||
op->func(key, value, op->data);
|
||||
return 1;
|
||||
}
|
||||
op++;
|
||||
}
|
||||
|
||||
struct uwsgi_custom_option *uco = uwsgi.custom_options;
|
||||
while (uco) {
|
||||
if (uwsgi_manage_custom_option(uco, key, value)) {
|
||||
return 1;
|
||||
}
|
||||
uco = uco->next;
|
||||
}
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_configure() {
|
||||
|
||||
int i;
|
||||
|
||||
// and now apply the remaining configs
|
||||
restart:
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
if (uwsgi.exported_opts[i]->configured)
|
||||
continue;
|
||||
uwsgi.dirty_config = 0;
|
||||
uwsgi.exported_opts[i]->configured = uwsgi_manage_opt(uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
|
||||
if (uwsgi.exported_opts[i]->configured == 0 && uwsgi.autoload) {
|
||||
uwsgi.dirty_config = uwsgi_try_autoload(uwsgi.exported_opts[i]->key);
|
||||
}
|
||||
if (uwsgi.dirty_config)
|
||||
goto restart;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
|
||||
char *tmp = NULL;
|
||||
@@ -1051,8 +974,11 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
fullname = minimal_name;
|
||||
}
|
||||
|
||||
magic_table['b'] = uwsgi.binary_path;
|
||||
magic_table['p'] = fullname;
|
||||
|
||||
magic_table['s'] = uwsgi_get_last_char(fullname, '/') + 1;
|
||||
|
||||
magic_table['d'] = uwsgi_concat2n(magic_table['p'], magic_table['s'] - magic_table['p'], "", 0);
|
||||
if (magic_table['d'][strlen(magic_table['d']) - 1] == '/') {
|
||||
tmp = magic_table['d'] + (strlen(magic_table['d']) - 1);
|
||||
@@ -1061,6 +987,23 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
#endif
|
||||
*tmp = 0;
|
||||
}
|
||||
|
||||
// clear optional vars
|
||||
magic_table['c'] = "";
|
||||
magic_table['e'] = "";
|
||||
magic_table['n'] = magic_table['s'];
|
||||
|
||||
magic_table['0'] = "";
|
||||
magic_table['1'] = "";
|
||||
magic_table['2'] = "";
|
||||
magic_table['3'] = "";
|
||||
magic_table['4'] = "";
|
||||
magic_table['5'] = "";
|
||||
magic_table['6'] = "";
|
||||
magic_table['7'] = "";
|
||||
magic_table['8'] = "";
|
||||
magic_table['9'] = "";
|
||||
|
||||
if (uwsgi_get_last_char(magic_table['d'], '/')) {
|
||||
magic_table['c'] = uwsgi_str(uwsgi_get_last_char(magic_table['d'], '/') + 1);
|
||||
if (magic_table['c'][strlen(magic_table['c']) - 1] == '/') {
|
||||
@@ -1084,16 +1027,31 @@ void config_magic_table_fill(char *filename, char **magic_table) {
|
||||
if (tmp)
|
||||
*tmp = '/';
|
||||
|
||||
if (uwsgi_get_last_char(filename, '.'))
|
||||
magic_table['e'] = uwsgi_get_last_char(filename, '.') + 1;
|
||||
if (uwsgi_get_last_char(magic_table['s'], '.'))
|
||||
magic_table['e'] = uwsgi_get_last_char(magic_table['s'], '.') + 1;
|
||||
if (uwsgi_get_last_char(magic_table['s'], '.'))
|
||||
magic_table['n'] = uwsgi_concat2n(magic_table['s'], uwsgi_get_last_char(magic_table['s'], '.') - magic_table['s'], "", 0);
|
||||
|
||||
reuse:
|
||||
magic_table['x'] = "";
|
||||
if (section) {
|
||||
magic_table['x'] = section+1;
|
||||
*section = ':';
|
||||
}
|
||||
|
||||
// first round ?
|
||||
if (!uwsgi.magic_table_first_round) {
|
||||
magic_table['O'] = magic_table['o'];
|
||||
magic_table['D'] = magic_table['d'];
|
||||
magic_table['S'] = magic_table['s'];
|
||||
magic_table['P'] = magic_table['p'];
|
||||
magic_table['C'] = magic_table['c'];
|
||||
magic_table['E'] = magic_table['e'];
|
||||
magic_table['N'] = magic_table['n'];
|
||||
magic_table['X'] = magic_table['x'];
|
||||
uwsgi.magic_table_first_round = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int find_worker_id(pid_t pid) {
|
||||
@@ -1111,10 +1069,10 @@ void warn_pipe() {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (uwsgi.threads < 2 && wsgi_req->uri_len > 0) {
|
||||
uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request %.*s (ip %.*s) !!!\n", wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr);
|
||||
uwsgi_log_verbose("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) on request %.*s (ip %.*s) !!!\n", wsgi_req->uri_len, wsgi_req->uri, wsgi_req->remote_addr_len, wsgi_req->remote_addr);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) !!!\n");
|
||||
uwsgi_log_verbose("SIGPIPE: writing to a closed pipe/socket/fd (probably the client disconnected) !!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1262,7 +1220,9 @@ void grace_them_all(int signum) {
|
||||
|
||||
if (uwsgi.lazy) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -1270,9 +1230,6 @@ void grace_them_all(int signum) {
|
||||
|
||||
uwsgi.status.gracefully_reloading = 1;
|
||||
|
||||
int waitpid_status;
|
||||
|
||||
|
||||
uwsgi_destroy_processes();
|
||||
|
||||
uwsgi_log("...gracefully killing workers...\n");
|
||||
@@ -1286,36 +1243,10 @@ void grace_them_all(int signum) {
|
||||
}
|
||||
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.auto_snapshot) {
|
||||
if (uwsgi.workers[i].snapshot > 0) {
|
||||
kill(uwsgi.workers[i].snapshot, SIGKILL);
|
||||
if (waitpid(uwsgi.workers[i].snapshot, &waitpid_status, 0) < 0) {
|
||||
uwsgi_error("waitpid()");
|
||||
}
|
||||
}
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
|
||||
uwsgi.workers[i].snapshot = 0;
|
||||
uwsgi.workers[i].destroy = 1;
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
else {
|
||||
uwsgi.workers[i].snapshot = uwsgi.workers[i].pid;
|
||||
kill(uwsgi.workers[i].pid, SIGURG);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.workers[i].pid > 0) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.auto_snapshot) {
|
||||
uwsgi.respawn_snapshots = uwsgi.numproc - uwsgi.auto_snapshot;
|
||||
if (!uwsgi.respawn_snapshots)
|
||||
uwsgi.respawn_snapshots = 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_nuclear_blast() {
|
||||
@@ -1374,23 +1305,6 @@ void harakiri() {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void snapshot_me(int signum) {
|
||||
// wakeup !!!
|
||||
if (uwsgi.snapshot) {
|
||||
uwsgi.snapshot = 0;
|
||||
uwsgi_set_processname(uwsgi.workers[uwsgi.mywid].name);
|
||||
return;
|
||||
}
|
||||
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
|
||||
if (uwsgi.threads > 1) {
|
||||
wait_for_threads();
|
||||
}
|
||||
uwsgi.snapshot = 1;
|
||||
uwsgi_set_processname(uwsgi.workers[uwsgi.mywid].snapshot_name);
|
||||
uwsgi_log("[snapshot] process %d taken\n", (int) getpid());
|
||||
}
|
||||
|
||||
void stats(int signum) {
|
||||
//fix this for better logging(this cause races)
|
||||
struct uwsgi_app *ua = NULL;
|
||||
@@ -1473,6 +1387,15 @@ void what_i_am_doing() {
|
||||
|
||||
|
||||
int unconfigured_hook(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->uh->modifier1 == 0 && !uwsgi.no_default_app) {
|
||||
if (uwsgi_apps_cnt > 0 && uwsgi.default_app > -1) {
|
||||
struct uwsgi_app *ua = &uwsgi_apps[uwsgi.default_app];
|
||||
if (uwsgi.p[ua->modifier1]->request != unconfigured_hook) {
|
||||
wsgi_req->uh->modifier1 = ua->modifier1;
|
||||
return uwsgi.p[ua->modifier1]->request(wsgi_req);
|
||||
}
|
||||
}
|
||||
}
|
||||
uwsgi_log("-- unavailable modifier requested: %d --\n", wsgi_req->uh->modifier1);
|
||||
return -1;
|
||||
}
|
||||
@@ -1505,7 +1428,7 @@ void uwsgi_exec_atexit(void) {
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_as_user_atexit) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1918,6 +1841,10 @@ static struct uwsgi_clock uwsgi_unix_clock = {
|
||||
.microseconds = uwsgi_unix_microseconds,
|
||||
};
|
||||
|
||||
void uwsgi_init_random() {
|
||||
srand((unsigned int) (uwsgi.start_tv.tv_usec * uwsgi.start_tv.tv_sec));
|
||||
}
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
int uwsgi_init(int argc, char *argv[], char *envp[]) {
|
||||
|
||||
@@ -1948,7 +1875,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
signal(SIGTERM, SIG_IGN);
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
|
||||
|
||||
//initialize masterpid with a default value
|
||||
masterpid = getpid();
|
||||
|
||||
@@ -1958,6 +1884,9 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
|
||||
init_magic_table(uwsgi.magic_table);
|
||||
|
||||
// initialize schemes
|
||||
uwsgi_setup_schemes();
|
||||
|
||||
// initialize the clock
|
||||
uwsgi_register_clock(&uwsgi_unix_clock);
|
||||
uwsgi_set_clock("unix");
|
||||
@@ -1988,6 +1917,12 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// set default values
|
||||
uwsgi_init_default();
|
||||
|
||||
// detect cpu cores
|
||||
#if defined(_SC_NPROCESSORS_ONLN)
|
||||
uwsgi.cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#elif defined(_SC_NPROCESSORS_CONF)
|
||||
uwsgi.cpus = sysconf(_SC_NPROCESSORS_CONF);
|
||||
#endif
|
||||
// set default logit hook
|
||||
uwsgi.logit = uwsgi_logit_simple;
|
||||
|
||||
@@ -2008,6 +1943,9 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// get startup time
|
||||
gettimeofday(&uwsgi.start_tv, NULL);
|
||||
|
||||
// initialize random engine
|
||||
uwsgi_init_random();
|
||||
|
||||
setlinebuf(stdout);
|
||||
|
||||
uwsgi.rl.rlim_cur = 0;
|
||||
@@ -2065,6 +2003,9 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_register_base_hooks();
|
||||
uwsgi_log_encoders_register_embedded();
|
||||
|
||||
// register base metrics (so plugins can override them)
|
||||
uwsgi_metrics_collectors_setup();
|
||||
|
||||
//initialize embedded plugins
|
||||
UWSGI_LOAD_EMBEDDED_PLUGINS
|
||||
// now a bit of magic, if the executable basename contains a 'uwsgi_' string,
|
||||
@@ -2081,7 +2022,10 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// set a couple of 'static' magic vars
|
||||
uwsgi.magic_table['v'] = uwsgi.cwd;
|
||||
uwsgi.magic_table['h'] = uwsgi.hostname;
|
||||
uwsgi.magic_table['t'] = uwsgi_64bit2str(uwsgi_now());
|
||||
uwsgi.magic_table['T'] = uwsgi_64bit2str(uwsgi_micros());
|
||||
uwsgi.magic_table['V'] = UWSGI_VERSION;
|
||||
uwsgi.magic_table['k'] = uwsgi_num2str(uwsgi.cpus);
|
||||
uwsgi.magic_table['['] = "\033";
|
||||
|
||||
// you can embed a ini file in the uWSGi binary with default options
|
||||
@@ -2103,16 +2047,14 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_apply_config_pass('@', uwsgi_simple_file_read);
|
||||
|
||||
// last pass: REFERENCEs
|
||||
uwsgi_apply_config_pass('%', uwsgi_get_exported_opt);
|
||||
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
// optional pass: MATH
|
||||
uwsgi_apply_config_pass('=', uwsgi_matheval_str);
|
||||
#endif
|
||||
uwsgi_apply_config_pass('%', uwsgi_manage_placeholder);
|
||||
|
||||
// ok, the options dictionary is available, lets manage it
|
||||
uwsgi_configure();
|
||||
|
||||
// fixup cwd
|
||||
if (uwsgi.force_cwd) uwsgi.cwd = uwsgi.force_cwd;
|
||||
|
||||
// run "asap" hooks
|
||||
uwsgi_hooks_run(uwsgi.hook_asap, "asap", 1);
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
@@ -2196,7 +2138,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_register_imperial_monitor("glob", uwsgi_imperial_monitor_glob_init, uwsgi_imperial_monitor_glob);
|
||||
|
||||
// setup stats pushers
|
||||
uwsgi_register_stats_pusher("file", uwsgi_stats_pusher_file);
|
||||
uwsgi_stats_pusher_setup();
|
||||
|
||||
// register embedded alarms
|
||||
@@ -2287,12 +2228,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_log_initial("*** big endian arch detected ***\n");
|
||||
#endif
|
||||
|
||||
#if defined(_SC_NPROCESSORS_ONLN)
|
||||
uwsgi.cpus = sysconf(_SC_NPROCESSORS_ONLN);
|
||||
#elif defined(_SC_NPROCESSORS_CONF)
|
||||
uwsgi.cpus = sysconf(_SC_NPROCESSORS_CONF);
|
||||
#endif
|
||||
|
||||
uwsgi_log_initial("detected number of CPU cores: %d\n", uwsgi.cpus);
|
||||
|
||||
|
||||
@@ -2385,7 +2320,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
|
||||
|
||||
// TODO pluginize basic Linux namespace support
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) && !defined(__ia64__)
|
||||
if (uwsgi.ns) {
|
||||
linux_namespace_start((void *) uwsgi.argv);
|
||||
// never here
|
||||
@@ -2393,7 +2328,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
else {
|
||||
#endif
|
||||
uwsgi_start((void *) uwsgi.argv);
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) && !defined(__ia64__)
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2410,9 +2345,11 @@ int uwsgi_start(void *v_argv) {
|
||||
#ifdef __linux__
|
||||
uwsgi_set_cgroup();
|
||||
|
||||
#if !defined(__ia64__)
|
||||
if (uwsgi.ns) {
|
||||
linux_namespace_jail();
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_in_jail, "in-jail", 1);
|
||||
@@ -2576,7 +2513,7 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
if ((unsigned long) uwsgi.max_fd < (unsigned long) uwsgi.async) {
|
||||
uwsgi_log("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
|
||||
uwsgi_log_initial("- your current max open files limit is %lu, this is lower than requested async cores !!! -\n", (unsigned long) uwsgi.max_fd);
|
||||
uwsgi.rl.rlim_cur = uwsgi.async;
|
||||
uwsgi.rl.rlim_max = uwsgi.async;
|
||||
if (!setrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
@@ -2588,7 +2525,7 @@ int uwsgi_start(void *v_argv) {
|
||||
uwsgi.async = (int) uwsgi.max_fd;
|
||||
}
|
||||
}
|
||||
uwsgi_log("- async cores set to %d - fd table size: %d\n", uwsgi.async, (int) uwsgi.max_fd);
|
||||
uwsgi_log_initial("- async cores set to %d - fd table size: %d\n", uwsgi.async, (int) uwsgi.max_fd);
|
||||
// optimization, this array maps file descriptor to requests
|
||||
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
@@ -2599,16 +2536,16 @@ int uwsgi_start(void *v_argv) {
|
||||
#endif
|
||||
|
||||
if (uwsgi.vhost) {
|
||||
uwsgi_log("VirtualHosting mode enabled.\n");
|
||||
uwsgi_log_initial("VirtualHosting mode enabled.\n");
|
||||
}
|
||||
|
||||
// setup locking
|
||||
uwsgi_setup_locking();
|
||||
if (uwsgi.use_thunder_lock) {
|
||||
uwsgi_log("thunder lock: enabled\n");
|
||||
uwsgi_log_initial("thunder lock: enabled\n");
|
||||
}
|
||||
else {
|
||||
uwsgi_log("thunder lock: disabled (you can enable it with --thunder-lock)\n");
|
||||
uwsgi_log_initial("thunder lock: disabled (you can enable it with --thunder-lock)\n");
|
||||
}
|
||||
|
||||
// allocate rpc structures
|
||||
@@ -2661,6 +2598,9 @@ int uwsgi_start(void *v_argv) {
|
||||
// initialize the exception handlers
|
||||
uwsgi_exception_setup_handlers();
|
||||
|
||||
// initialize socket protocols (do it after caching !!!)
|
||||
uwsgi_protocols_register();
|
||||
|
||||
/* plugin initialization */
|
||||
for (i = 0; i < uwsgi.gp_cnt; i++) {
|
||||
if (uwsgi.gp[i]->init) {
|
||||
@@ -2763,7 +2703,8 @@ int uwsgi_start(void *v_argv) {
|
||||
!uwsgi.emperor &&
|
||||
!uwsgi.command_mode &&
|
||||
!uwsgi.daemons_cnt &&
|
||||
!uwsgi.crons
|
||||
!uwsgi.crons &&
|
||||
!uwsgi.emperor_proxy
|
||||
#ifdef UWSGI_SSL
|
||||
&& !uwsgi.legions
|
||||
#endif
|
||||
@@ -2898,6 +2839,9 @@ unsafe:
|
||||
// set a default request structure (for loading apps...)
|
||||
uwsgi.wsgi_req = &uwsgi.workers[0].cores[0].req;
|
||||
|
||||
// ok, let's initialize the metrics subsystem
|
||||
uwsgi_setup_metrics();
|
||||
|
||||
// cores are allocated, lets allocate logformat (if required)
|
||||
if (uwsgi.logformat) {
|
||||
uwsgi_build_log_format(uwsgi.logformat);
|
||||
@@ -3104,6 +3048,7 @@ next2:
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// END OF INITIALIZATION
|
||||
|
||||
// !!! from now on, we could be in the master or in a worker !!!
|
||||
@@ -3243,11 +3188,6 @@ void uwsgi_worker_run() {
|
||||
uwsgi_unix_signal(SIGINT, end_me);
|
||||
uwsgi_unix_signal(SIGTERM, end_me);
|
||||
|
||||
if (uwsgi.auto_snapshot) {
|
||||
uwsgi_unix_signal(SIGURG, snapshot_me);
|
||||
}
|
||||
|
||||
|
||||
uwsgi_unix_signal(SIGUSR1, stats);
|
||||
signal(SIGUSR2, (void *) &what_i_am_doing);
|
||||
if (!uwsgi.ignore_sigpipe) {
|
||||
@@ -3311,15 +3251,6 @@ void uwsgi_ignition() {
|
||||
|
||||
int i;
|
||||
|
||||
// snapshot workers do not enter the loop until a specific signal (SIGURG) is raised...
|
||||
if (uwsgi.snapshot) {
|
||||
wait_for_call_of_duty:
|
||||
uwsgi_sig_pause();
|
||||
if (uwsgi.snapshot)
|
||||
goto wait_for_call_of_duty;
|
||||
uwsgi_log("[snapshot] process %d is the new worker %d\n", (int) getpid(), uwsgi.mywid);
|
||||
}
|
||||
|
||||
for (i = 0; i < 256; i++) {
|
||||
if (uwsgi.p[i]->hijack_worker) {
|
||||
uwsgi.p[i]->hijack_worker();
|
||||
@@ -3362,9 +3293,6 @@ wait_for_call_of_duty:
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.snapshot) {
|
||||
uwsgi_ignition();
|
||||
}
|
||||
// end of the process...
|
||||
end_me(0);
|
||||
}
|
||||
@@ -3442,7 +3370,26 @@ void build_options() {
|
||||
pos += c;
|
||||
}
|
||||
}
|
||||
// custom_options are not added to uwsgi.options
|
||||
|
||||
uco = uwsgi.custom_options;
|
||||
while (uco) {
|
||||
uwsgi.options[pos].name = uco->name;
|
||||
if (uco->has_args) {
|
||||
uwsgi.options[pos].type = required_argument;
|
||||
}
|
||||
else {
|
||||
uwsgi.options[pos].type = no_argument;
|
||||
}
|
||||
// custom options should be immediate
|
||||
uwsgi.options[pos].flags = UWSGI_OPT_IMMEDIATE;
|
||||
// help shows the option definition
|
||||
uwsgi.options[pos].help = uco->value;
|
||||
uwsgi.options[pos].data = uco;
|
||||
uwsgi.options[pos].func = uwsgi_opt_custom;
|
||||
|
||||
pos++;
|
||||
uco = uco->next;
|
||||
}
|
||||
|
||||
|
||||
pos = 0;
|
||||
@@ -3481,21 +3428,6 @@ void build_options() {
|
||||
op++;
|
||||
pos++;
|
||||
}
|
||||
uco = uwsgi.custom_options;
|
||||
while (uco) {
|
||||
uwsgi.long_options[pos].name = uco->name;
|
||||
if (uco->has_args) {
|
||||
uwsgi.long_options[pos].has_arg = required_argument;
|
||||
}
|
||||
else {
|
||||
uwsgi.long_options[pos].has_arg = no_argument;
|
||||
}
|
||||
uwsgi.long_options[pos].flag = 0;
|
||||
// add 1000 to avoid short_options collision
|
||||
uwsgi.long_options[pos].val = 1000 + pos;
|
||||
pos++;
|
||||
uco = uco->next;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3558,7 +3490,7 @@ void uwsgi_init_all_apps() {
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_pre_app) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -3626,7 +3558,7 @@ void uwsgi_init_all_apps() {
|
||||
|
||||
uwsgi_foreach(usl, uwsgi.call_post_app) {
|
||||
if (uwsgi_call_symbol(usl->value)) {
|
||||
uwsgi_log("unaable to call function \"%s\"\n", usl->value);
|
||||
uwsgi_log("unable to call function \"%s\"\n", usl->value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3922,6 +3854,58 @@ void uwsgi_opt_add_socket(char *opt, char *value, void *protocol) {
|
||||
uwsgi_sock->proto_name = protocol;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
void uwsgi_opt_add_ssl_socket(char *opt, char *value, void *protocol) {
|
||||
char *client_ca = NULL;
|
||||
|
||||
// build socket, certificate and key file
|
||||
char *sock = uwsgi_str(value);
|
||||
char *crt = strchr(sock, ',');
|
||||
if (!crt) {
|
||||
uwsgi_log("invalid https-socket syntax must be socket,crt,key\n");
|
||||
exit(1);
|
||||
}
|
||||
*crt = '\0'; crt++;
|
||||
char *key = strchr(crt, ',');
|
||||
if (!key) {
|
||||
uwsgi_log("invalid https-socket syntax must be socket,crt,key\n");
|
||||
exit(1);
|
||||
}
|
||||
*key = '\0'; key++;
|
||||
|
||||
char *ciphers = strchr(key, ',');
|
||||
if (ciphers) {
|
||||
*ciphers = '\0'; ciphers++;
|
||||
client_ca = strchr(ciphers, ',');
|
||||
if (client_ca) {
|
||||
*client_ca = '\0'; client_ca++;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(sock));
|
||||
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
|
||||
uwsgi_sock->proto_name = protocol;
|
||||
|
||||
// ok we have the socket, initialize ssl if required
|
||||
if (!uwsgi.ssl_initialized) {
|
||||
uwsgi_ssl_init();
|
||||
}
|
||||
|
||||
// initialize ssl context
|
||||
uwsgi_sock->ssl_ctx = uwsgi_ssl_new_server_context(uwsgi_sock->name, crt, key, ciphers, client_ca);
|
||||
if (!uwsgi_sock->ssl_ctx) {
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void uwsgi_opt_add_socket_no_defer(char *opt, char *value, void *protocol) {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(value));
|
||||
uwsgi_sock->name_len = strlen(uwsgi_sock->name);
|
||||
uwsgi_sock->proto_name = protocol;
|
||||
uwsgi_sock->no_defer = 1;
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_lazy_socket(char *opt, char *value, void *protocol) {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi_new_socket(generate_socket_name(value));
|
||||
uwsgi_sock->proto_name = protocol;
|
||||
@@ -3930,7 +3914,7 @@ void uwsgi_opt_add_lazy_socket(char *opt, char *value, void *protocol) {
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_placeholder(char *opt, char *value, void *none) {
|
||||
void uwsgi_opt_set_placeholder(char *opt, char *value, void *ph) {
|
||||
|
||||
char *p = strchr(value, '=');
|
||||
if (!p) {
|
||||
@@ -3939,7 +3923,7 @@ void uwsgi_opt_set_placeholder(char *opt, char *value, void *none) {
|
||||
}
|
||||
|
||||
p[0] = 0;
|
||||
add_exported_option(uwsgi_str(value), p + 1, 1);
|
||||
add_exported_option_do(uwsgi_str(value), p + 1, 0, ph ? 1 : 0);
|
||||
p[0] = '=';
|
||||
|
||||
}
|
||||
@@ -3997,6 +3981,14 @@ void uwsgi_opt_set_umask(char *opt, char *value, void *mode) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_exit(char *opt, char *value, void *none) {
|
||||
int exit_code = 1;
|
||||
if (value) {
|
||||
exit_code = atoi(value);
|
||||
}
|
||||
exit(exit_code);
|
||||
}
|
||||
|
||||
void uwsgi_opt_print(char *opt, char *value, void *str) {
|
||||
if (str) {
|
||||
fprintf(stdout, "%s\n", (char *) str);
|
||||
@@ -4021,7 +4013,18 @@ void uwsgi_opt_set_gid(char *opt, char *value, void *none) {
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
void uwsgi_opt_set_cap(char *opt, char *value, void *none) {
|
||||
uwsgi_build_cap(value);
|
||||
uwsgi.cap_count = uwsgi_build_cap(value, &uwsgi.cap);
|
||||
if (uwsgi.cap_count == 0) {
|
||||
uwsgi_log("[security] empty capabilities mask !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
void uwsgi_opt_set_emperor_cap(char *opt, char *value, void *none) {
|
||||
uwsgi.emperor_cap_count = uwsgi_build_cap(value, &uwsgi.emperor_cap);
|
||||
if (uwsgi.emperor_cap_count == 0) {
|
||||
uwsgi_log("[security] empty capabilities mask !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef __linux__
|
||||
@@ -4211,6 +4214,7 @@ int uwsgi_zerg_attach(char *value) {
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
free(zerg);
|
||||
}
|
||||
|
||||
close(zerg_fd);
|
||||
@@ -4291,39 +4295,45 @@ void uwsgi_opt_deprecated(char *opt, char *value, void *message) {
|
||||
|
||||
void uwsgi_opt_load(char *opt, char *filename, void *none) {
|
||||
|
||||
// here we need to avoid setting upper magic vars
|
||||
int orig_magic = uwsgi.magic_table_first_round;
|
||||
uwsgi.magic_table_first_round = 1;
|
||||
|
||||
if (uwsgi_endswith(filename, ".ini")) {
|
||||
uwsgi_opt_load_ini(opt, filename, none);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
#ifdef UWSGI_XML
|
||||
if (uwsgi_endswith(filename, ".xml")) {
|
||||
uwsgi_opt_load_xml(opt, filename, none);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
#ifdef UWSGI_YAML
|
||||
if (uwsgi_endswith(filename, ".yaml")) {
|
||||
uwsgi_opt_load_yml(opt, filename, none);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
if (uwsgi_endswith(filename, ".yml")) {
|
||||
uwsgi_opt_load_yml(opt, filename, none);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
#ifdef UWSGI_JSON
|
||||
if (uwsgi_endswith(filename, ".json")) {
|
||||
uwsgi_opt_load_json(opt, filename, none);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
if (uwsgi_endswith(filename, ".js")) {
|
||||
uwsgi_opt_load_json(opt, filename, none);
|
||||
return;
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
// fallback to pluggable system
|
||||
uwsgi_opt_load_config(opt, filename, none);
|
||||
end:
|
||||
uwsgi.magic_table_first_round = orig_magic;
|
||||
}
|
||||
|
||||
void uwsgi_opt_logic(char *opt, char *arg, void *func) {
|
||||
@@ -4572,3 +4582,23 @@ void uwsgi_update_pidfiles() {
|
||||
uwsgi_write_pidfile(uwsgi.pidfile2);
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_binary_append_data(char *opt, char *value, void *none) {
|
||||
|
||||
size_t size;
|
||||
char *buf = uwsgi_open_and_read(value, &size, 0, NULL);
|
||||
|
||||
uint64_t file_len = size;
|
||||
|
||||
if (write(1, buf, size) != (ssize_t) size) {
|
||||
uwsgi_error("uwsgi_opt_binary_append_data()/write()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (write(1, &file_len, 8) != 8) {
|
||||
uwsgi_error("uwsgi_opt_binary_append_data()/write()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
// pong received, send anther ping
|
||||
// pong received, send another ping
|
||||
if (now - wsgi_req->websocket_last_ping >= uwsgi.websockets_ping_freq) {
|
||||
return uwsgi_websockets_ping(wsgi_req);
|
||||
}
|
||||
|
||||
@@ -151,6 +151,8 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
|
||||
}
|
||||
/* We can safely free resources */
|
||||
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
xmlCleanupParser();
|
||||
|
||||
@@ -267,6 +269,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
|
||||
|
||||
} while (!done);
|
||||
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
// we can safely free, as we have a copy of datas
|
||||
XML_ParserFree(parser);
|
||||
|
||||
@@ -280,6 +280,7 @@ next:
|
||||
}
|
||||
#endif
|
||||
|
||||
if (colon) colon[0] = ':';
|
||||
|
||||
}
|
||||
|
||||
|
||||
+3
-2
@@ -123,12 +123,13 @@ int uwsgi_gzip_fix(z_stream *z, uint32_t crc32, struct uwsgi_buffer *ub, size_t
|
||||
if (!gzipped0) goto end;
|
||||
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
|
||||
free(gzipped0);
|
||||
if (uwsgi_buffer_u32le(ub, crc32)) goto end;
|
||||
if (uwsgi_buffer_u32le(ub, len)) goto end;
|
||||
if (uwsgi_buffer_u32le(ub, crc32)) goto end2;
|
||||
if (uwsgi_buffer_u32le(ub, len)) goto end2;
|
||||
deflateEnd(z);
|
||||
return 0;
|
||||
end:
|
||||
if (gzipped0) free(gzipped0);
|
||||
end2:
|
||||
deflateEnd(z);
|
||||
return -1;
|
||||
}
|
||||
|
||||
+27
-33
@@ -26,9 +26,6 @@ struct uwsgi_carbon {
|
||||
unsigned long long *last_busyness_values;
|
||||
unsigned long long *current_busyness_values;
|
||||
int *was_busy;
|
||||
int need_retry;
|
||||
time_t last_update;
|
||||
time_t next_retry;
|
||||
int max_retries;
|
||||
int retry_delay;
|
||||
char *root_node;
|
||||
@@ -40,6 +37,7 @@ struct uwsgi_carbon {
|
||||
int zero_avg;
|
||||
uint64_t last_requests;
|
||||
struct uwsgi_stats_pusher *pusher;
|
||||
int use_metrics;
|
||||
} u_carbon;
|
||||
|
||||
static struct uwsgi_option carbon_options[] = {
|
||||
@@ -55,6 +53,7 @@ static struct uwsgi_option carbon_options[] = {
|
||||
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{"carbon-idle-avg", required_argument, 0, "average values source during idle period (no requests), can be \"last\", \"zero\", \"none\" (default is last)", uwsgi_opt_set_str, &u_carbon.idle_avg, 0},
|
||||
{"carbon-use-metrics", no_argument, 0, "don't compute all statistics, use metrics subsystem data instead (warning! key names will be different)", uwsgi_opt_true, &u_carbon.use_metrics, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -108,7 +107,7 @@ static void carbon_post_init() {
|
||||
|
||||
if (u_carbon.freq < 1) u_carbon.freq = 60;
|
||||
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
|
||||
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
|
||||
if (u_carbon.max_retries < 0) u_carbon.max_retries = 0;
|
||||
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
|
||||
if (!u_carbon.id) {
|
||||
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
|
||||
@@ -153,14 +152,13 @@ static void carbon_post_init() {
|
||||
u_carbon.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
|
||||
}
|
||||
|
||||
// set next update to now()+retry_delay, this way we will have first flush just after start
|
||||
u_carbon.last_update = uwsgi_now() - u_carbon.freq + u_carbon.retry_delay;
|
||||
|
||||
uwsgi_log("[carbon] carbon plugin started, %is frequency, %is timeout, max retries %i, retry delay %is\n",
|
||||
u_carbon.freq, u_carbon.timeout, u_carbon.max_retries, u_carbon.retry_delay);
|
||||
|
||||
struct uwsgi_stats_pusher_instance *uspi = uwsgi_stats_pusher_add(u_carbon.pusher, NULL);
|
||||
uspi->freq = u_carbon.freq;
|
||||
uspi->retry_delay = u_carbon.retry_delay;
|
||||
uspi->max_retries = u_carbon.max_retries;
|
||||
// no need to generate the json
|
||||
uspi->raw=1;
|
||||
}
|
||||
@@ -185,14 +183,15 @@ static int carbon_write(int fd, char *fmt,...) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
static int carbon_push_stats(int retry_cycle, time_t now) {
|
||||
struct carbon_server_list *usl = u_carbon.servers_data;
|
||||
if (!u_carbon.servers_data) return;
|
||||
if (!u_carbon.servers_data) return 0;
|
||||
int i;
|
||||
int fd;
|
||||
int wok;
|
||||
char *ip;
|
||||
char *carbon_address = NULL;
|
||||
int needs_retry;
|
||||
|
||||
for (i = 0; i < uwsgi.numproc; i++) {
|
||||
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
|
||||
@@ -200,7 +199,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
u_carbon.was_busy[i-1] += uwsgi_worker_is_busy(i+1);
|
||||
}
|
||||
|
||||
u_carbon.need_retry = 0;
|
||||
needs_retry = 0;
|
||||
while(usl) {
|
||||
if (retry_cycle && usl->healthy)
|
||||
// skip healthy servers during retry cycle
|
||||
@@ -228,15 +227,7 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
fd = uwsgi_connect(carbon_address, u_carbon.timeout, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", carbon_address);
|
||||
if (usl->errors < u_carbon.max_retries) {
|
||||
u_carbon.need_retry = 1;
|
||||
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
|
||||
} else {
|
||||
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
|
||||
carbon_address, u_carbon.max_retries);
|
||||
usl->healthy = 0;
|
||||
usl->errors = 0;
|
||||
}
|
||||
needs_retry = 1;
|
||||
usl->healthy = 0;
|
||||
usl->errors++;
|
||||
free(carbon_address);
|
||||
@@ -246,6 +237,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
// put the socket in non-blocking mode
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
if (u_carbon.use_metrics) goto metrics_loop;
|
||||
|
||||
unsigned long long total_rss = 0;
|
||||
unsigned long long total_vsz = 0;
|
||||
unsigned long long total_tx = 0;
|
||||
@@ -380,6 +373,18 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
wok = carbon_write(fd, "%s%s.%s.harakiri %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_harakiri, (unsigned long long) now);
|
||||
if (!wok) goto clear;
|
||||
|
||||
metrics_loop:
|
||||
if (u_carbon.use_metrics) {
|
||||
struct uwsgi_metric *um = uwsgi.metrics;
|
||||
while(um) {
|
||||
uwsgi_rlock(uwsgi.metrics_lock);
|
||||
wok = carbon_write(fd, "%s%s.%s.%.*s %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, um->name_len, um->name, (unsigned long long) *um->value, (unsigned long long) now);
|
||||
uwsgi_rwunlock(uwsgi.metrics_lock);
|
||||
if (!wok) goto clear;
|
||||
um = um->next;
|
||||
}
|
||||
}
|
||||
|
||||
usl->healthy = 1;
|
||||
usl->errors = 0;
|
||||
|
||||
@@ -390,23 +395,12 @@ clear:
|
||||
nxt:
|
||||
usl = usl->next;
|
||||
}
|
||||
if (!retry_cycle) u_carbon.last_update = uwsgi_now();
|
||||
if (u_carbon.need_retry)
|
||||
// timeouts and retries might cause additional lags in carbon cycles, we will adjust timer to fix that
|
||||
u_carbon.last_update -= u_carbon.timeout;
|
||||
|
||||
return needs_retry;
|
||||
}
|
||||
|
||||
static void carbon_push(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
|
||||
|
||||
if (u_carbon.need_retry && now >= u_carbon.next_retry) {
|
||||
carbon_push_stats(1, now);
|
||||
}
|
||||
else {
|
||||
// update
|
||||
u_carbon.need_retry = 0;
|
||||
carbon_push_stats(0, now);
|
||||
|
||||
}
|
||||
uspi->needs_retry = carbon_push_stats(uspi->retries, now);
|
||||
}
|
||||
|
||||
static void carbon_cleanup() {
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int cheaper_backlog2_algo(void) {
|
||||
int cheaper_backlog2_algo(int can_spawn) {
|
||||
|
||||
int i;
|
||||
#ifdef __linux__
|
||||
@@ -22,7 +22,9 @@ int cheaper_backlog2_algo(void) {
|
||||
int backlog = 0;
|
||||
#endif
|
||||
|
||||
if (backlog > (int)uwsgi.cheaper_overload) {
|
||||
// if can_spawn == 0 we cannot spawn any new worker
|
||||
// this is set to 1 if --cheaper-rss-limit-* options are used and running workers are exceeding resources limit
|
||||
if (can_spawn && backlog > (int)uwsgi.cheaper_overload) {
|
||||
// activate the first available worker (taking step into account)
|
||||
int decheaped = 0;
|
||||
// search for cheaped workers
|
||||
|
||||
@@ -142,7 +142,7 @@ int spawn_emergency_worker(int backlog) {
|
||||
#endif
|
||||
|
||||
|
||||
int cheaper_busyness_algo(void) {
|
||||
int cheaper_busyness_algo(int can_spawn) {
|
||||
|
||||
int i;
|
||||
// we use microseconds
|
||||
@@ -243,11 +243,12 @@ int cheaper_busyness_algo(void) {
|
||||
uwsgi_cheaper_busyness_global.tolerance_counter = 0;
|
||||
|
||||
int decheaped = 0;
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step) break;
|
||||
if (can_spawn) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
|
||||
decheaped++;
|
||||
if (decheaped >= uwsgi.cheaper_step) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -271,15 +272,15 @@ int cheaper_busyness_algo(void) {
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%%, will spawn %d new worker(s)\n",
|
||||
uwsgi.cheaper_overload, avg_busyness, decheaped);
|
||||
} else {
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers (%d)\n",
|
||||
uwsgi.cheaper_overload, avg_busyness, uwsgi.numproc);
|
||||
uwsgi_log("[busyness] %llus average busyness is at %llu%% but we already started maximum number of workers available with current limits (%d)\n",
|
||||
uwsgi.cheaper_overload, avg_busyness, active_workers);
|
||||
}
|
||||
|
||||
// return the maximum number of workers to spawn
|
||||
return decheaped;
|
||||
|
||||
#ifdef __linux__
|
||||
} else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
} else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
return spawn_emergency_worker(backlog);
|
||||
#endif
|
||||
|
||||
@@ -347,14 +348,14 @@ int cheaper_busyness_algo(void) {
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
else if (backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
else if (can_spawn && backlog > uwsgi_cheaper_busyness_global.backlog_alert && active_workers < uwsgi.numproc) {
|
||||
// we check for backlog overload every cycle
|
||||
return spawn_emergency_worker(backlog);
|
||||
}
|
||||
else if (backlog > 0) {
|
||||
if (uwsgi_cheaper_busyness_global.backlog_is_nonzero) {
|
||||
// backlog was > 0 last time, check timestamp and spawn workers if needed
|
||||
if ((now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) {
|
||||
if (can_spawn && (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000 >= uwsgi_cheaper_busyness_global.backlog_nonzero_alert) {
|
||||
uwsgi_log("[busyness] backlog was non-zero for %llu second(s), spawning new worker(s)\n", (now - uwsgi_cheaper_busyness_global.backlog_nonzero_since)/1000000);
|
||||
uwsgi_cheaper_busyness_global.backlog_nonzero_since = now;
|
||||
return spawn_emergency_worker(backlog);
|
||||
@@ -391,4 +392,3 @@ struct uwsgi_plugin cheaper_busyness_plugin = {
|
||||
.options = uwsgi_cheaper_busyness_options,
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -187,11 +187,12 @@ void uwsgi_opt_corerouter_zerg(char *opt, char *value, void *cr) {
|
||||
|
||||
close(zerg_fd);
|
||||
|
||||
for(j=0;j<count;j++) {
|
||||
if (zerg[j] == -1) break;
|
||||
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
|
||||
ugs->zerg = optarg;
|
||||
}
|
||||
for(j=0;j<count;j++) {
|
||||
if (zerg[j] == -1) break;
|
||||
ugs = uwsgi_new_gateway_socket_from_fd(zerg[j], ucr->name);
|
||||
ugs->zerg = optarg;
|
||||
}
|
||||
free(zerg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
}
|
||||
}
|
||||
// destroy an instance
|
||||
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 6)) {
|
||||
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 7)) {
|
||||
struct uwsgi_instance *ui = emperor_get(name);
|
||||
if (!ui) {
|
||||
uwsgi_log("[emperor-zeromq] unknown instance \"%s\"\n", name);
|
||||
|
||||
@@ -190,21 +190,23 @@ static ssize_t fr_instance_connected(struct corerouter_peer *peer) {
|
||||
// called after receaving the uwsgi header (read vars)
|
||||
static ssize_t fr_recv_uwsgi_vars(struct corerouter_peer *main_peer) {
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) main_peer->in->buf;
|
||||
// better to store it as the original buf address could change
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
// increase buffer if needed
|
||||
if (uwsgi_buffer_fix(main_peer->in, uh->pktsize+4))
|
||||
if (uwsgi_buffer_fix(main_peer->in, pktsize+4))
|
||||
return -1;
|
||||
ssize_t len = cr_read_exact(main_peer, uh->pktsize+4, "fr_recv_uwsgi_vars()");
|
||||
ssize_t len = cr_read_exact(main_peer, pktsize+4, "fr_recv_uwsgi_vars()");
|
||||
if (!len) return 0;
|
||||
|
||||
// headers received, ready to choose the instance
|
||||
if (main_peer->in->pos == (size_t)(uh->pktsize+4)) {
|
||||
if (main_peer->in->pos == (size_t)(pktsize+4)) {
|
||||
struct uwsgi_corerouter *ucr = main_peer->session->corerouter;
|
||||
|
||||
struct corerouter_peer *new_peer = uwsgi_cr_peer_add(main_peer->session);
|
||||
new_peer->last_hook_read = fr_instance_read;
|
||||
|
||||
// find the hostname
|
||||
if (uwsgi_hooked_parse(main_peer->in->buf+4, uh->pktsize, fr_get_hostname, (void *) new_peer)) {
|
||||
if (uwsgi_hooked_parse(main_peer->in->buf+4, pktsize, fr_get_hostname, (void *) new_peer)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
uWSGI forkpty-router
|
||||
|
||||
can use the uwsgi protocol, modifier2 means:
|
||||
|
||||
0 -> stdin
|
||||
1-99 -> UNIX signal
|
||||
100 -> window rows (pktsize is the window size)
|
||||
101 -> window cols (pktsize is the window size)
|
||||
|
||||
*/
|
||||
|
||||
#include <uwsgi.h>
|
||||
@@ -9,9 +16,9 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__GNU_kFreeBSD__)
|
||||
#include <pty.h>
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#include <util.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <libutil.h>
|
||||
@@ -24,22 +31,45 @@ extern struct uwsgi_server uwsgi;
|
||||
static struct uwsgi_forkptyrouter {
|
||||
struct uwsgi_corerouter cr;
|
||||
char *cmd;
|
||||
uint16_t win_rows;
|
||||
uint16_t win_cols;
|
||||
} ufpty;
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct forkptyrouter_session {
|
||||
struct corerouter_session session;
|
||||
// use the uwsgi protocol ?
|
||||
int uwsgi;
|
||||
size_t restore_size;
|
||||
struct winsize w;
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
static void uwsgi_opt_forkpty_urouter(char *opt, char *value, void *cr) {
|
||||
struct uwsgi_corerouter *ucr = (struct uwsgi_corerouter *) cr;
|
||||
struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(value, ucr->name);
|
||||
ugs->no_defer = 1;
|
||||
ugs->mode = 1;
|
||||
ucr->has_sockets++;
|
||||
}
|
||||
|
||||
|
||||
static struct uwsgi_option forkptyrouter_options[] = {
|
||||
{"forkptyrouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
|
||||
{"forkpty-router", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_undeferred_corerouter, &ufpty, 0},
|
||||
|
||||
{"forkptyurouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_forkpty_urouter, &ufpty, 0},
|
||||
{"forkpty-urouter", required_argument, 0, "run the forkptyrouter on the specified address", uwsgi_opt_forkpty_urouter, &ufpty, 0},
|
||||
|
||||
{"forkptyrouter-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkpty-router-command", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkptyrouter-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
{"forkpty-router-cmd", required_argument, 0, "run the specified command on every connection (default: /bin/sh)", uwsgi_opt_set_str, &ufpty.cmd, 0},
|
||||
|
||||
{"forkptyrouter-rows", required_argument, 0, "set forkptyrouter default pty window rows", uwsgi_opt_set_16bit, &ufpty.win_rows, 0},
|
||||
{"forkptyrouter-cols", required_argument, 0, "set forkptyrouter default pty window cols", uwsgi_opt_set_16bit, &ufpty.win_cols, 0},
|
||||
|
||||
{"forkptyrouter-processes", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
|
||||
{"forkptyrouter-workers", required_argument, 0, "prefork the specified number of forkptyrouter processes", uwsgi_opt_set_int, &ufpty.cr.processes, 0},
|
||||
{"forkptyrouter-zerg", required_argument, 0, "attach the forkptyrouter to a zerg server", uwsgi_opt_corerouter_zerg, &ufpty, 0},
|
||||
@@ -61,6 +91,7 @@ static struct uwsgi_option forkptyrouter_options[] = {
|
||||
|
||||
// write to backend
|
||||
static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
|
||||
ssize_t len = cr_write(peer, "fpty_instance_write()");
|
||||
// end on empty write
|
||||
if (!len) return 0;
|
||||
@@ -68,7 +99,13 @@ static ssize_t fpty_instance_write(struct corerouter_peer *peer) {
|
||||
// the chunk has been sent, start (again) reading from client and instances
|
||||
if (cr_write_complete(peer)) {
|
||||
// reset the buffer
|
||||
peer->out->pos = 0;
|
||||
if (fpty_session->uwsgi) {
|
||||
if (uwsgi_buffer_decapitate(peer->out, peer->out->pos)) return -1;
|
||||
peer->out->pos = fpty_session->restore_size;
|
||||
}
|
||||
else {
|
||||
peer->out->pos = 0;
|
||||
}
|
||||
cr_reset_hooks(peer);
|
||||
}
|
||||
|
||||
@@ -91,6 +128,42 @@ static ssize_t fpty_write(struct corerouter_peer *main_peer) {
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t fpty_parse_uwsgi(struct corerouter_peer *peer) {
|
||||
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) peer->session;
|
||||
for(;;) {
|
||||
if (peer->in->pos < 4) return 0;
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) peer->in->buf;
|
||||
uint16_t pktsize = uh->pktsize;
|
||||
switch(uh->modifier2) {
|
||||
case 0:
|
||||
// stdin
|
||||
if ((size_t) (pktsize+4) > peer->in->pos) return 0;
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
return pktsize;
|
||||
case 100:
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
fpty_session->w.ws_row = pktsize;
|
||||
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
|
||||
// rows
|
||||
break;
|
||||
case 101:
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
fpty_session->w.ws_col = pktsize;
|
||||
ioctl(peer->session->peers->fd, TIOCSWINSZ, &fpty_session->w);
|
||||
// cols
|
||||
break;
|
||||
default:
|
||||
if (uwsgi_buffer_decapitate(peer->in, 4)) return -1;
|
||||
// send signal
|
||||
kill(fpty_session->pid, uh->modifier2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// read from backend
|
||||
static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
|
||||
ssize_t len = cr_read(peer, "fpty_instance_read()");
|
||||
@@ -106,10 +179,22 @@ static ssize_t fpty_instance_read(struct corerouter_peer *peer) {
|
||||
|
||||
// read from client
|
||||
static ssize_t fpty_read(struct corerouter_peer *main_peer) {
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) main_peer->session;
|
||||
ssize_t len = cr_read(main_peer, "fpty_read()");
|
||||
if (!len) return 0;
|
||||
|
||||
main_peer->session->peers->out = main_peer->in;
|
||||
if (fpty_session->uwsgi) {
|
||||
ssize_t rlen = fpty_parse_uwsgi(main_peer);
|
||||
if (rlen < 0) return -1;
|
||||
if (rlen == 0) return 1;
|
||||
|
||||
fpty_session->restore_size = main_peer->in->pos - rlen;
|
||||
main_peer->session->peers->out = main_peer->in;
|
||||
main_peer->session->peers->out->pos = rlen;
|
||||
}
|
||||
else {
|
||||
main_peer->session->peers->out = main_peer->in;
|
||||
}
|
||||
main_peer->session->peers->out_pos = 0;
|
||||
|
||||
cr_write_to_backend(main_peer->session->peers, fpty_instance_write);
|
||||
@@ -137,12 +222,19 @@ static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsg
|
||||
cs->close = fpty_session_close;
|
||||
|
||||
struct forkptyrouter_session *fpty_session = (struct forkptyrouter_session *) cs;
|
||||
if (ugs->mode == 1) {
|
||||
fpty_session->uwsgi = 1;
|
||||
}
|
||||
|
||||
// default terminal size
|
||||
fpty_session->w.ws_row = ufpty.win_rows ? ufpty.win_rows : 24;
|
||||
fpty_session->w.ws_col = ufpty.win_cols ? ufpty.win_cols : 80;
|
||||
|
||||
// add a new peer
|
||||
struct corerouter_peer *peer = uwsgi_cr_peer_add(cs);
|
||||
|
||||
// on new connection generate a new pty
|
||||
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, NULL);
|
||||
fpty_session->pid = forkpty(&peer->fd, NULL, NULL, &fpty_session->w);
|
||||
if (fpty_session->pid < 0) {
|
||||
uwsgi_error("forkpty()");
|
||||
return -1;
|
||||
@@ -156,23 +248,23 @@ static int forkptyrouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsg
|
||||
argv[1] = "-c";
|
||||
argv[2] = ufpty.cmd;
|
||||
argv[3] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
execv(argv[0], argv);
|
||||
}
|
||||
else {
|
||||
char *argv[2];
|
||||
argv[0] = ufpty.cmd;
|
||||
argv[1] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
execv(argv[0], argv);
|
||||
}
|
||||
}
|
||||
else {
|
||||
char *argv[2];
|
||||
argv[0] = "/bin/sh";
|
||||
argv[1] = NULL;
|
||||
execve(argv[0], argv, uwsgi.environ);
|
||||
execv(argv[0], argv);
|
||||
}
|
||||
// never here;
|
||||
uwsgi_error("forkptyrouter_alloc_session()/execve()");
|
||||
uwsgi_error("forkptyrouter_alloc_session()/execv()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
+271
-13
@@ -2,7 +2,7 @@
|
||||
|
||||
/*
|
||||
|
||||
Soon before official Go 1.1, we understand supporting Go in a fork() heavy
|
||||
Soon before official Go 1.1, we understood supporting Go in a fork() heavy
|
||||
environment was not blessed by the Go community.
|
||||
|
||||
Instead of completely dropping support for Go, we studied how the gccgo project works and we
|
||||
@@ -16,8 +16,31 @@
|
||||
the uwsgi.Run() go function directly calls the uwsgi_takeover() function (it automatically
|
||||
manages mules, spoolers and workers)
|
||||
|
||||
As well as before each core maps to a goroutine mapped to a real pthread. (goroutines called
|
||||
from your apps are native goroutines)
|
||||
The plugin implements goroutines too.
|
||||
|
||||
On startup a goroutine is created for each socket and signals file descriptors.
|
||||
|
||||
For every request a new goroutine is created too.
|
||||
|
||||
The wsgi_request * structure is attached to the "closure" field of the goroutine (PAY ATTENTION)
|
||||
|
||||
even if the loop engine makes use of the async mode, pthreads could be spawned all over the place.
|
||||
For such a reason a mutex is created avoiding the global wsgi_req structures to be clobbered
|
||||
|
||||
Contrary to the standard way Go apps are deployed, the plugin supports loading shared libraries.
|
||||
While this is a common approach in other environments, the Go community prefers monolithic binaries.
|
||||
|
||||
As always, choose the model that best suite for you. Eventually building a single uWSGI binary with your Go
|
||||
app embedded is pretty easy:
|
||||
|
||||
|
||||
CFLAGS=-DUWSGI_GCCGO_MONOLITHIC UWSGI_ADDITIONAL_SOURCES=t/go/uploadtest.go UWSGI_PROFILE=gccgo make
|
||||
|
||||
or you can add the following two directives in a build profile:
|
||||
|
||||
cflags = -DUWSGI_GCCGO_MONOLITHIC
|
||||
additional_sources = t/go/uploadtest.go
|
||||
|
||||
|
||||
*/
|
||||
|
||||
@@ -25,25 +48,29 @@ extern struct uwsgi_server uwsgi;
|
||||
struct uwsgi_plugin gccgo_plugin;
|
||||
|
||||
struct uwsgi_gccgo{
|
||||
// 1 if a main is loaded
|
||||
int initialized;
|
||||
struct uwsgi_string_list *libs;
|
||||
char *args;
|
||||
pthread_mutex_t wsgi_req_lock;
|
||||
} ugccgo;
|
||||
|
||||
/*
|
||||
shortcut for enabling the "goroutines" loop engine
|
||||
*/
|
||||
static void uwsgi_opt_setup_goroutines(char *opt, char *value, void *foobar) {
|
||||
// set async mode
|
||||
uwsgi_opt_set_int(opt, value, &uwsgi.async);
|
||||
// set loop engine
|
||||
uwsgi.loop = "goroutines";
|
||||
}
|
||||
*/
|
||||
|
||||
struct uwsgi_option uwsgi_gccgo_options[] = {
|
||||
{"go-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"gccgo-load", required_argument, 0, "load a go shared library in the process address space, eventually patching main.main and __go_init_main", uwsgi_opt_add_string_list, &ugccgo.libs, 0},
|
||||
{"go-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
{"gccgo-args", required_argument, 0, "set go commandline arguments", uwsgi_opt_set_str, &ugccgo.args, 0},
|
||||
// {"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
|
||||
{"goroutines", required_argument, 0, "a shortcut setting optimal options for goroutine-based apps, takes the number of max goroutines to spawn as argument", uwsgi_opt_setup_goroutines, NULL, UWSGI_OPT_THREADS},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -51,27 +78,46 @@ struct uwsgi_option uwsgi_gccgo_options[] = {
|
||||
// no_split_stack is the key to avoid crashing !!!
|
||||
void* runtime_m(void) __attribute__ ((noinline, no_split_stack));
|
||||
|
||||
// initialize runtime
|
||||
void runtime_check(void);
|
||||
void runtime_args(int, char **);
|
||||
void runtime_osinit(void);
|
||||
void runtime_schedinit(void);
|
||||
void *__go_go(void *, void *);
|
||||
void runtime_main(void);
|
||||
void runtime_mstart(void *);
|
||||
|
||||
// spawn a goroutine
|
||||
void *__go_go(void *, void *);
|
||||
|
||||
// api functions exposed
|
||||
extern void uwsgigo_request(void *, void *) __asm__ ("go.uwsgi.RequestHandler");
|
||||
extern void* uwsgigo_env(void *) __asm__ ("go.uwsgi.Env");
|
||||
extern void* uwsgigo_env_add(void *, void *, uint16_t, void *, uint16_t) __asm__ ("go.uwsgi.EnvAdd");
|
||||
extern void uwsgigo_run_core(int) __asm__ ("go.uwsgi.RunCore");
|
||||
extern void uwsgigo_signal_handler(void *, uint8_t) __asm__ ("go.uwsgi.SignalHandler");
|
||||
//extern void uwsgigo_loop(void) __asm__ ("go.uwsgi.Loop");
|
||||
|
||||
// for goroutines
|
||||
void runtime_netpollinit(void);
|
||||
void runtime_starttheworld(void);
|
||||
void *runtime_pollOpen(int) __asm__ ("net.runtime_pollOpen");
|
||||
void runtime_pollClose(void *) __asm__ ("net.runtime_pollClose");
|
||||
void runtime_pollUnblock(void *) __asm__ ("net.runtime_pollUnblock");
|
||||
int runtime_pollWait(void *, int) __asm__ ("net.runtime_pollWait");
|
||||
void runtime_pollSetDeadline(void *, int64_t, int) __asm__ ("net.runtime_pollSetDeadline");
|
||||
void runtime_gosched(void);
|
||||
// the current goroutine
|
||||
void *runtime_g(void);
|
||||
// we use the closure field to store the wsgi_req structure
|
||||
void __go_set_closure(void *);
|
||||
void *__go_get_closure(void);
|
||||
|
||||
static void mainstart(void *arg __attribute__((unused))) {
|
||||
runtime_main();
|
||||
}
|
||||
|
||||
#ifndef UWSGI_GCCGO_MONOLITHIC
|
||||
void uwsgigo_main_main(void) __asm__ ("main.main");
|
||||
void uwsgigo_main_init(void) __asm__ ("__go_init_main");
|
||||
#endif
|
||||
|
||||
void (*uwsgigo_hook_init)(void);
|
||||
void (*uwsgigo_hook_main)(void);
|
||||
@@ -102,6 +148,14 @@ int uwsgi_gccgo_helper_register_signal(uint8_t signum, char *receiver, void *han
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_initialize() {
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi_log("!!! the Go runtime cannot work in multithreaded modes !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
#ifdef UWSGI_GCCGO_MONOLITHIC
|
||||
uwsgigo_hook_init = dlsym(RTLD_DEFAULT, "__go_init_main");
|
||||
uwsgigo_hook_main = dlsym(RTLD_DEFAULT, "main.main");
|
||||
#endif
|
||||
struct uwsgi_string_list *usl = ugccgo.libs;
|
||||
while(usl) {
|
||||
void *handle = dlopen(usl->value, RTLD_NOW | RTLD_GLOBAL);
|
||||
@@ -109,9 +163,16 @@ static void uwsgi_gccgo_initialize() {
|
||||
uwsgi_log("unable to open go shared library: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
|
||||
uwsgigo_hook_init = dlsym(handle, "__go_init_main");
|
||||
uwsgigo_hook_main = dlsym(handle, "main.main");
|
||||
void *g_init = dlsym(handle, "__go_init_main");
|
||||
void *g_main = dlsym(handle, "main.main");
|
||||
if (g_init && g_main) {
|
||||
uwsgigo_hook_init = g_init;
|
||||
uwsgigo_hook_main = g_main;
|
||||
uwsgi_log("[uwsgi-gccgo] loaded %s as main\n", usl->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-gccgo] loaded %s\n", usl->value);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
@@ -119,6 +180,8 @@ static void uwsgi_gccgo_initialize() {
|
||||
return;
|
||||
}
|
||||
|
||||
ugccgo.initialized = 1;
|
||||
|
||||
// Go runtime initialization
|
||||
int argc = 0;
|
||||
if (ugccgo.args) {
|
||||
@@ -131,7 +194,7 @@ static void uwsgi_gccgo_initialize() {
|
||||
}
|
||||
runtime_check();
|
||||
if (argc > 0) {
|
||||
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 1));
|
||||
char **argv = uwsgi_calloc(sizeof(char *) * (argc + 2));
|
||||
char *argv_list = uwsgi_str(ugccgo.args);
|
||||
char *p, *ctx = NULL;
|
||||
int n = 0;
|
||||
@@ -145,6 +208,7 @@ static void uwsgi_gccgo_initialize() {
|
||||
char *argv[2] = {0,0};
|
||||
runtime_args(0, argv);
|
||||
}
|
||||
|
||||
runtime_osinit();
|
||||
runtime_schedinit();
|
||||
__go_go(mainstart, NULL);
|
||||
@@ -153,6 +217,10 @@ static void uwsgi_gccgo_initialize() {
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
|
||||
if (!ugccgo.initialized) {
|
||||
uwsgi_log("!!! Go runtime not initialized !!!\n");
|
||||
goto end;
|
||||
}
|
||||
/* Standard GO request */
|
||||
if (!wsgi_req->uh->pktsize) {
|
||||
uwsgi_log("Empty GO request. skip.\n");
|
||||
@@ -170,6 +238,7 @@ static int uwsgi_gccgo_request(struct wsgi_request *wsgi_req) {
|
||||
i++;
|
||||
}
|
||||
uwsgigo_request(wsgi_req->async_environ, wsgi_req);
|
||||
end:
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -178,15 +247,204 @@ static void uwsgi_gccgo_after_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_signal_handler(uint8_t signum, void *handler) {
|
||||
if (!ugccgo.initialized) return -1;
|
||||
uwsgigo_signal_handler(handler, signum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define free_req_queue pthread_mutex_lock(&ugccgo.wsgi_req_lock);uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = wsgi_req; pthread_mutex_unlock(&ugccgo.wsgi_req_lock)
|
||||
|
||||
static void uwsgi_gccgo_request_goroutine(void *arg) {
|
||||
|
||||
struct wsgi_request *wsgi_req = (struct wsgi_request *) arg;
|
||||
|
||||
// map wsgi_req to the goroutine
|
||||
__go_set_closure(wsgi_req);
|
||||
|
||||
int ret,status;
|
||||
|
||||
for(;;) {
|
||||
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
|
||||
wsgi_req->switches++;
|
||||
|
||||
if (ret <= 0) {
|
||||
goto end;
|
||||
}
|
||||
|
||||
retry:
|
||||
status = wsgi_req->socket->proto(wsgi_req);
|
||||
if (status < 0) {
|
||||
goto end;
|
||||
}
|
||||
else if (status == 0) {
|
||||
break;
|
||||
}
|
||||
if (uwsgi_is_again()) continue;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
for(;;) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->request(wsgi_req) <= UWSGI_OK) {
|
||||
goto end;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
// yield
|
||||
runtime_gosched();
|
||||
}
|
||||
|
||||
end:
|
||||
uwsgi_close_request(wsgi_req);
|
||||
free_req_queue;
|
||||
}
|
||||
|
||||
static struct wsgi_request *uwsgi_gccgo_current_wsgi_req(void) {
|
||||
return (struct wsgi_request *) __go_get_closure();
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_wait_read_hook(int fd, int timeout) {
|
||||
void *pdesc = runtime_pollOpen(fd);
|
||||
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
|
||||
runtime_pollSetDeadline(pdesc, t, 'r');
|
||||
int ret = runtime_pollWait(pdesc, 'r');
|
||||
runtime_pollUnblock(pdesc);
|
||||
runtime_pollClose(pdesc);
|
||||
if (ret == 0) return 1;
|
||||
// timeout
|
||||
if (ret == 2) return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int uwsgi_gccgo_wait_write_hook(int fd, int timeout) {
|
||||
void *pdesc = runtime_pollOpen(fd);
|
||||
int64_t t = (uwsgi_micros() * 1000LL) + (((int64_t)timeout) * 1000LL * 1000LL * 1000LL);
|
||||
runtime_pollSetDeadline(pdesc, t, 'w');
|
||||
int ret = runtime_pollWait(pdesc, 'w');
|
||||
runtime_pollUnblock(pdesc);
|
||||
runtime_pollClose(pdesc);
|
||||
if (ret == 0) return 1;
|
||||
// timeout
|
||||
if (ret == 2) return 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
this goroutine manages signals
|
||||
*/
|
||||
static void uwsgi_gccgo_signal_goroutine(void *arg) {
|
||||
int *fd = (int *) arg;
|
||||
void *pdesc = runtime_pollOpen(*fd);
|
||||
for(;;) {
|
||||
runtime_pollWait(pdesc, 'r');
|
||||
retry:
|
||||
uwsgi_receive_signal(*fd, "worker", uwsgi.mywid);
|
||||
if (uwsgi_is_again()) continue;
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_socket_goroutine(void *arg) {
|
||||
struct uwsgi_socket *uwsgi_sock = (struct uwsgi_socket *) arg;
|
||||
struct wsgi_request *wsgi_req = NULL;
|
||||
void *pdesc = runtime_pollOpen(uwsgi_sock->fd);
|
||||
// wait for connection
|
||||
for(;;) {
|
||||
runtime_pollWait(pdesc, 'r');
|
||||
retry:
|
||||
pthread_mutex_lock(&ugccgo.wsgi_req_lock);
|
||||
wsgi_req = find_first_available_wsgi_req();
|
||||
pthread_mutex_unlock(&ugccgo.wsgi_req_lock);
|
||||
|
||||
if (wsgi_req == NULL) {
|
||||
uwsgi_async_queue_is_full(uwsgi_now());
|
||||
// try rescheduling...
|
||||
// we do not use runtime_gosched() as we want to call the netpoll loop too
|
||||
runtime_pollUnblock(pdesc);
|
||||
runtime_pollClose(pdesc);
|
||||
pdesc = runtime_pollOpen(uwsgi_sock->fd);
|
||||
continue;
|
||||
}
|
||||
|
||||
// fill wsgi_request structure
|
||||
wsgi_req_setup(wsgi_req, wsgi_req->async_id, uwsgi_sock );
|
||||
|
||||
// mark core as used
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 1;
|
||||
|
||||
// accept the connection (since uWSGI 1.5 all of the sockets are non-blocking)
|
||||
if (wsgi_req_simple_accept(wsgi_req, uwsgi_sock->fd)) {
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].in_request = 0;
|
||||
free_req_queue;
|
||||
if (uwsgi_is_again()) continue;
|
||||
goto retry;
|
||||
}
|
||||
|
||||
wsgi_req->start_of_request = uwsgi_micros();
|
||||
wsgi_req->start_of_request_in_sec = wsgi_req->start_of_request/1000000;
|
||||
|
||||
// enter harakiri mode
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
|
||||
set_harakiri(uwsgi.shared->options[UWSGI_OPTION_HARAKIRI]);
|
||||
}
|
||||
|
||||
// spawn the new goroutine
|
||||
__go_go(uwsgi_gccgo_request_goroutine, wsgi_req);
|
||||
goto retry;
|
||||
}
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_loop() {
|
||||
if (!ugccgo.initialized) {
|
||||
uwsgi_log("no go.main code loaded !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
// initialize the log protecting the wsgi_req structures
|
||||
pthread_mutex_init(&ugccgo.wsgi_req_lock, NULL);
|
||||
|
||||
// hooks
|
||||
uwsgi.current_wsgi_req = uwsgi_gccgo_current_wsgi_req;
|
||||
uwsgi.wait_write_hook = uwsgi_gccgo_wait_write_hook;
|
||||
uwsgi.wait_read_hook = uwsgi_gccgo_wait_read_hook;
|
||||
|
||||
// ininitialize Go I/O loop
|
||||
runtime_netpollinit();
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.signal_socket);
|
||||
__go_go(uwsgi_gccgo_signal_goroutine, &uwsgi.my_signal_socket);
|
||||
}
|
||||
|
||||
// start a goroutine for each socket
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (!uwsgi_sock->next) {
|
||||
uwsgi_gccgo_socket_goroutine(uwsgi_sock);
|
||||
}
|
||||
else {
|
||||
__go_go(uwsgi_gccgo_socket_goroutine, uwsgi_sock);
|
||||
}
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
// never here
|
||||
}
|
||||
|
||||
static void uwsgi_gccgo_on_load() {
|
||||
uwsgi_register_loop( (char *) "go", uwsgi_gccgo_loop);
|
||||
uwsgi_register_loop( (char *) "goroutine", uwsgi_gccgo_loop);
|
||||
uwsgi_register_loop( (char *) "goroutines", uwsgi_gccgo_loop);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin gccgo_plugin = {
|
||||
.name = "gccgo",
|
||||
.modifier1 = 11,
|
||||
.options = uwsgi_gccgo_options,
|
||||
//.on_load = uwsgi_gccgo_on_load,
|
||||
.on_load = uwsgi_gccgo_on_load,
|
||||
.request = uwsgi_gccgo_request,
|
||||
.after_request = uwsgi_gccgo_after_request,
|
||||
.post_fork = uwsgi_gccgo_initialize,
|
||||
|
||||
+45
-2
@@ -1,5 +1,12 @@
|
||||
package uwsgi
|
||||
|
||||
/*
|
||||
|
||||
this is a very low-level module, full of performance hacks
|
||||
do not take it as a good example of go coding...
|
||||
|
||||
*/
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"net/http"
|
||||
@@ -20,17 +27,27 @@ func uwsgi_response_add_header(*interface{}, *byte, uint16, *byte, uint16) int
|
||||
func uwsgi_request_body_read(*interface{}, *byte, uint64) int
|
||||
//extern uwsgi_gccgo_helper_register_signal
|
||||
func uwsgi_register_signal(uint8, *byte, func(uint8)) int
|
||||
//extern uwsgi_cache_magic_get
|
||||
func uwsgi_cache_magic_get(*byte, uint16, *uint64, *uint64, *byte) *byte;
|
||||
//extern __go_byte_array_to_string
|
||||
func __go_byte_array_to_string(*byte, int) string
|
||||
//extern free
|
||||
func free(* byte)
|
||||
|
||||
var uwsgi_signals_gc [256]func(uint8)
|
||||
var uwsgi_env_gc map[interface{}]interface{}
|
||||
|
||||
func Env(wsgi_req *interface{}) *map[string]string {
|
||||
var env map[string]string
|
||||
env = make(map[string]string)
|
||||
uwsgi_env_gc[wsgi_req] = &env
|
||||
return &env
|
||||
}
|
||||
|
||||
func EnvAdd(env *map[string]string, k *[65536]byte, kl uint16, v *[65536]byte, vl uint16) {
|
||||
(*env)[ string((*k)[0:kl]) ] = string((*v)[0:vl])
|
||||
func EnvAdd(env *map[string]string, k *byte, kl uint16, v *byte, vl uint16) {
|
||||
s_k := __go_byte_array_to_string(k, int(kl))
|
||||
s_v := __go_byte_array_to_string(v, int(vl))
|
||||
(*env)[ s_k ] = s_v
|
||||
}
|
||||
|
||||
type ResponseWriter struct {
|
||||
@@ -98,9 +115,13 @@ func RequestHandler(env *map[string]string, wsgi_req *interface{}) {
|
||||
w := ResponseWriter{httpReq, wsgi_req,http.Header{},false}
|
||||
http.DefaultServeMux.ServeHTTP(&w, httpReq)
|
||||
}
|
||||
delete(uwsgi_env_gc, wsgi_req)
|
||||
}
|
||||
|
||||
func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
|
||||
if (receiver == "") {
|
||||
receiver = "worker"
|
||||
}
|
||||
var b []byte = []byte(receiver)
|
||||
if (uwsgi_register_signal(signum, &b[0], handler) < 0) {
|
||||
return false
|
||||
@@ -109,10 +130,32 @@ func RegisterSignal(signum uint8, receiver string, handler func(uint8)) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// get an item from the cache
|
||||
func CacheGet(key string, cache string) string {
|
||||
|
||||
var b_key []byte = []byte(key)
|
||||
var v_len uint64 = 0
|
||||
var expires uint64 = 0
|
||||
var value *byte
|
||||
|
||||
if (cache == "") {
|
||||
value = uwsgi_cache_magic_get(&b_key[0], uint16(len(b_key)), &v_len, &expires, nil)
|
||||
} else {
|
||||
b_cache := []byte(cache)
|
||||
value = uwsgi_cache_magic_get(&b_key[0], uint16(len(b_key)), &v_len, &expires, &b_cache[0])
|
||||
}
|
||||
|
||||
ret := __go_byte_array_to_string(value, int(v_len))
|
||||
free(value)
|
||||
return ret
|
||||
}
|
||||
|
||||
|
||||
func SignalHandler(handler func(uint8), signum uint8) {
|
||||
handler(signum)
|
||||
}
|
||||
|
||||
func Run() {
|
||||
uwsgi_env_gc = make(map[interface{}]interface{})
|
||||
uwsgi_takeover()
|
||||
}
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
import os
|
||||
NAME='gccgo'
|
||||
|
||||
CFLAGS = ['-g']
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lgo']
|
||||
GCC_LIST = ['gccgo_plugin', 'uwsgi.go']
|
||||
|
||||
def post_build(config):
|
||||
if os.path.exists('plugins/gccgo/uwsgi.go.o'):
|
||||
if os.system("objcopy -j .go_export plugins/gccgo/uwsgi.go.o plugins/gccgo/uwsgi.gox") != 0:
|
||||
os._exit(1)
|
||||
print("*** uwsgi.gox available in %s/plugins/gccgo ***" % os.getcwd())
|
||||
@@ -291,7 +291,9 @@ request:
|
||||
}
|
||||
|
||||
end:
|
||||
Py_DECREF(greenlet_switch);
|
||||
if (greenlet_switch) {
|
||||
Py_DECREF(greenlet_switch);
|
||||
}
|
||||
end2:
|
||||
Py_DECREF(current_greenlet);
|
||||
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
#include <uwsgi.h>
|
||||
#include <api/glfs.h>
|
||||
|
||||
#ifdef UWSGI_MATHEVAL
|
||||
#error currently the glusterfs plugins is not compatible with uWSGI built with matheval support
|
||||
#endif
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
@@ -16,6 +16,22 @@ static struct uwsgi_option greenlet_options[] = {
|
||||
{ 0, 0, 0, 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
struct wsgi_request *uwsgi_greenlet_current_wsgi_req(void) {
|
||||
struct wsgi_request *wsgi_req = NULL;
|
||||
PyObject *current_greenlet = (PyObject *)PyGreenlet_GetCurrent();
|
||||
PyObject *py_wsgi_req = PyObject_GetAttrString(current_greenlet, "uwsgi_wsgi_req");
|
||||
// not in greenlet
|
||||
if (!py_wsgi_req) {
|
||||
uwsgi_log("[BUG] current_wsgi_req NOT FOUND !!!\n");
|
||||
goto end;
|
||||
}
|
||||
wsgi_req = (struct wsgi_request*) PyLong_AsLong(py_wsgi_req);
|
||||
Py_DECREF(py_wsgi_req);
|
||||
end:
|
||||
Py_DECREF(current_greenlet);
|
||||
return wsgi_req;
|
||||
}
|
||||
|
||||
static void gil_greenlet_get() {
|
||||
pthread_setspecific(up.upt_gil_key, (void *) PyGILState_Ensure());
|
||||
}
|
||||
@@ -26,9 +42,11 @@ static void gil_greenlet_release() {
|
||||
|
||||
static PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
|
||||
|
||||
struct wsgi_request *wsgi_req = uwsgi.wsgi_req;
|
||||
|
||||
async_schedule_to_req_green();
|
||||
|
||||
Py_DECREF(ugl.gl[uwsgi.wsgi_req->async_id]);
|
||||
Py_DECREF(ugl.gl[wsgi_req->async_id]);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
@@ -46,6 +64,7 @@ static void greenlet_schedule_to_req() {
|
||||
|
||||
if (!uwsgi.wsgi_req->suspended) {
|
||||
ugl.gl[id] = PyGreenlet_New(ugl.callable, NULL);
|
||||
PyObject_SetAttrString((PyObject *)ugl.gl[id], "uwsgi_wsgi_req", PyLong_FromLong((long) uwsgi.wsgi_req));
|
||||
uwsgi.wsgi_req->suspended = 1;
|
||||
}
|
||||
|
||||
@@ -54,7 +73,13 @@ static void greenlet_schedule_to_req() {
|
||||
uwsgi.p[modifier1]->suspend(NULL);
|
||||
}
|
||||
|
||||
PyGreenlet_Switch(ugl.gl[id], NULL, NULL);
|
||||
PyObject *ret = PyGreenlet_Switch(ugl.gl[id], NULL, NULL);
|
||||
if (!ret) {
|
||||
PyErr_Print();
|
||||
uwsgi_log_verbose("[BUG] unable to switch greenlet !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
if (uwsgi.p[modifier1]->resume) {
|
||||
uwsgi.p[modifier1]->resume(NULL);
|
||||
@@ -71,7 +96,13 @@ static void greenlet_schedule_to_main(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->suspend) {
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->suspend(wsgi_req);
|
||||
}
|
||||
PyGreenlet_Switch(ugl.main, NULL, NULL);
|
||||
PyObject *ret = PyGreenlet_Switch(ugl.main, NULL, NULL);
|
||||
if (!ret) {
|
||||
PyErr_Print();
|
||||
uwsgi_log_verbose("[BUG] unable to switch greenlet !!!\n");
|
||||
exit(1);
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
if (uwsgi.p[wsgi_req->uh->modifier1]->resume) {
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->resume(wsgi_req);
|
||||
}
|
||||
@@ -93,7 +124,10 @@ static void greenlet_init_apps(void) {
|
||||
up.gil_release = gil_greenlet_release;
|
||||
}
|
||||
|
||||
// blindy call it as the stackless gil engine is already set
|
||||
// map wsgi_req to greenlet object
|
||||
uwsgi.current_wsgi_req = uwsgi_greenlet_current_wsgi_req;
|
||||
|
||||
// blindly call it as the stackless gil engine is already set
|
||||
UWSGI_GET_GIL
|
||||
|
||||
|
||||
@@ -101,7 +135,9 @@ static void greenlet_init_apps(void) {
|
||||
|
||||
ugl.gl = uwsgi_malloc( sizeof(PyGreenlet *) * uwsgi.async );
|
||||
ugl.main = PyGreenlet_GetCurrent();
|
||||
Py_INCREF(ugl.main);
|
||||
ugl.callable = PyCFunction_New(uwsgi_greenlet_request_method, NULL);
|
||||
Py_INCREF(ugl.callable);
|
||||
uwsgi_log("enabled greenlet engine\n");
|
||||
|
||||
uwsgi.schedule_to_main = greenlet_schedule_to_main;
|
||||
|
||||
@@ -139,7 +139,7 @@ void uwsgi_opt_https2(char *opt, char *value, void *cr) {
|
||||
|
||||
#ifdef UWSGI_SPDY
|
||||
spdyerror:
|
||||
uwsgi_log("unable to inizialize SPDY settings buffers\n");
|
||||
uwsgi_log("unable to initialize SPDY settings buffers\n");
|
||||
exit(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ JNIEXPORT jobject JNICALL uwsgi_jvm_api_rpc(JNIEnv *env, jclass c, jobject j_arg
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
jobject argvj[256];
|
||||
uint16_t size = 0;
|
||||
uint64_t size = 0;
|
||||
|
||||
size_t args = uwsgi_jvm_array_len(j_args);
|
||||
if (args < 2) return NULL;
|
||||
@@ -1277,7 +1277,7 @@ void uwsgi_jvm_release_bytearray(jobject o, char *str) {
|
||||
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, o, (jbyte *)str, 0);
|
||||
}
|
||||
|
||||
static uint16_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
static uint64_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
|
||||
jvalue args[1];
|
||||
jobject str_array = (*ujvm_env)->NewObjectArray(ujvm_env, argc, ujvm.str_class, NULL);
|
||||
if (!str_array) return 0;
|
||||
@@ -1294,9 +1294,10 @@ static uint16_t uwsgi_jvm_rpc(void *func, uint8_t argc, char **argv, uint16_t ar
|
||||
return 0;
|
||||
}
|
||||
size_t rlen = uwsgi_jvm_strlen(ret);
|
||||
if (rlen <= 0xffff) {
|
||||
if (rlen > 0) {
|
||||
*buffer = uwsgi_malloc(rlen);
|
||||
char *b = uwsgi_jvm_str2c(ret);
|
||||
memcpy(buffer, b, rlen);
|
||||
memcpy(*buffer, b, rlen);
|
||||
uwsgi_jvm_release_chars(ret, b);
|
||||
uwsgi_jvm_local_unref(ret);
|
||||
return rlen;
|
||||
|
||||
@@ -7,12 +7,18 @@ JVM_INCPATH = None
|
||||
JVM_LIBPATH = None
|
||||
|
||||
operating_system = os.uname()[0].lower()
|
||||
arch = os.uname()[4]
|
||||
|
||||
try:
|
||||
arch = os.environ['JVM_ARCH']
|
||||
except:
|
||||
arch = os.uname()[4].lower()
|
||||
|
||||
if arch in ('i686', 'x86', 'x86_32'):
|
||||
arch = 'i386'
|
||||
elif arch in ('x86_64',):
|
||||
arch = 'amd64'
|
||||
elif arch.startswith('arm'):
|
||||
arch = 'arm'
|
||||
|
||||
# try to detect the JVM
|
||||
if operating_system == 'darwin':
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
#include <uwsgi.h>
|
||||
#include <ffi.h>
|
||||
|
||||
ffi_type *uwsgi_libffi_get_type(char *what, size_t *skip) {
|
||||
if (!uwsgi_startswith(what, "int:", 4)) { *skip = 4; return &ffi_type_sint32;}
|
||||
if (!uwsgi_startswith(what, "sint:", 5)) { *skip = 5; return &ffi_type_sint32;}
|
||||
if (!uwsgi_startswith(what, "uint:", 5)) { *skip = 5;return &ffi_type_uint32;}
|
||||
return &ffi_type_pointer;
|
||||
}
|
||||
|
||||
void *uwsgi_libffi_get_value(char *what, ffi_type *t) {
|
||||
if (t == &ffi_type_sint32) {
|
||||
int32_t *num = uwsgi_malloc(sizeof(int32_t));
|
||||
*num = atoi(what);
|
||||
return num;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int uwsgi_libffi_hook(char *arg) {
|
||||
size_t argc = 0;
|
||||
size_t i;
|
||||
char **argv = uwsgi_split_quoted(arg, strlen(arg), " \t", &argc);
|
||||
if (!argc) goto end;
|
||||
|
||||
void *func = dlsym(RTLD_DEFAULT, argv[0]);
|
||||
if (!func) goto destroy;
|
||||
|
||||
ffi_cif cif;
|
||||
ffi_type **args_type = (ffi_type **) uwsgi_malloc(sizeof(ffi_type) * (argc-1));
|
||||
void **values = uwsgi_malloc(sizeof(void*) * (argc-1));
|
||||
for(i=1;i<argc;i++) {
|
||||
size_t skip = 0;
|
||||
args_type[i-1] = uwsgi_libffi_get_type(argv[i], &skip);
|
||||
void *v = uwsgi_libffi_get_value(argv[i] + skip, args_type[i-1]);
|
||||
values[i-1] = v ? v : &argv[i];
|
||||
uwsgi_log("%d = %s %p\n", i, argv[i], values[i-1]);
|
||||
}
|
||||
|
||||
if (ffi_prep_cif(&cif, FFI_DEFAULT_ABI, argc-1, &ffi_type_sint64, args_type) == FFI_OK) {
|
||||
int64_t rc = 0;
|
||||
uwsgi_log("ready to call\n");
|
||||
ffi_call(&cif, func, &rc, values);
|
||||
}
|
||||
|
||||
uwsgi_log("ready to call2\n");
|
||||
for(i=0;i<(argc-1);i++) {
|
||||
char **ptr = (char **) values[i];
|
||||
if (*ptr != argv[i+1]) {
|
||||
free(values[i]);
|
||||
}
|
||||
}
|
||||
free(args_type);
|
||||
free(values);
|
||||
destroy:
|
||||
for(i=0;i<argc;i++) {
|
||||
free(argv[i]);
|
||||
}
|
||||
end:
|
||||
free(argv);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_libffi_setup() {
|
||||
uwsgi_register_hook("ffi", uwsgi_libffi_hook);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin libffi_plugin = {
|
||||
.name = "libffi",
|
||||
.on_load = uwsgi_libffi_setup,
|
||||
};
|
||||
@@ -0,0 +1,5 @@
|
||||
NAME='libffi'
|
||||
CFLAGS=[]
|
||||
LDFLAGS=[]
|
||||
LIBS=['-lffi']
|
||||
GCC_LIST=['libffi']
|
||||
@@ -670,7 +670,7 @@ static int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
|
||||
|
||||
}
|
||||
|
||||
static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
static uint64_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
|
||||
|
||||
uint8_t i;
|
||||
const char *sv;
|
||||
@@ -702,8 +702,9 @@ static uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t a
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("sv = %s sl = %lu\n", sv, (unsigned long) sl);
|
||||
#endif
|
||||
if (sl <= 0xffff) {
|
||||
memcpy(buffer, sv, sl);
|
||||
if (sl > 0) {
|
||||
*buffer = uwsgi_malloc(sl);
|
||||
memcpy(*buffer, sv, sl);
|
||||
lua_pop(L, 1);
|
||||
return sl;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
#include <uwsgi.h>
|
||||
#include <matheval.h>
|
||||
|
||||
static char *uwsgi_route_var_math(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
|
||||
char *ret = NULL;
|
||||
// avoid crash
|
||||
if (!wsgi_req->var_cnt) return NULL;
|
||||
// we make a bit of fun here, we do a copy of the vars buffer (+1 byte for final zero) and zeor-pad all of the strings
|
||||
char *vars_buf = uwsgi_malloc(wsgi_req->uh->pktsize + keylen + 1);
|
||||
char **names = uwsgi_malloc(sizeof(char *) * (wsgi_req->var_cnt/2));
|
||||
double *values = uwsgi_calloc(sizeof(double) * (wsgi_req->var_cnt/2));
|
||||
int i,j = 0;
|
||||
char *ptr = vars_buf;
|
||||
for (i = wsgi_req->var_cnt-1; i > 0; i -= 2) {
|
||||
memcpy(ptr, wsgi_req->hvec[i-1].iov_base, wsgi_req->hvec[i-1].iov_len);
|
||||
names[j] = ptr;
|
||||
ptr += wsgi_req->hvec[i-1].iov_len;
|
||||
*ptr++=0;
|
||||
char *num = ptr;
|
||||
memcpy(ptr, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
|
||||
ptr += wsgi_req->hvec[i].iov_len;
|
||||
*ptr++=0;
|
||||
values[j] = strtod(num, NULL);
|
||||
j++;
|
||||
}
|
||||
|
||||
char *expr = ptr;
|
||||
memcpy(ptr, key, keylen); ptr += keylen;
|
||||
*ptr++=0;
|
||||
|
||||
void *e = evaluator_create(expr);
|
||||
if (!e) goto end;
|
||||
double n = evaluator_evaluate(e, j, names, values);
|
||||
evaluator_destroy(e);
|
||||
ret = uwsgi_num2str((int)n);
|
||||
*vallen = strlen(ret);
|
||||
end:
|
||||
free(vars_buf);
|
||||
free(names);
|
||||
free(values);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void router_matheval_register() {
|
||||
struct uwsgi_route_var *urv = uwsgi_register_route_var("math", uwsgi_route_var_math);
|
||||
urv->need_free = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin matheval_plugin = {
|
||||
.name = "matheval",
|
||||
.on_load = router_matheval_register,
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='matheval'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmatheval']
|
||||
GCC_LIST = ['math']
|
||||
@@ -84,6 +84,7 @@ struct uwsgi_option uwsgi_mono_options[] = {
|
||||
{"mono-assembly", required_argument, 0, "load the specified main assembly (default: uwsgi.dll)", uwsgi_opt_set_str, &umono.assembly_name, 0},
|
||||
{"mono-exec", required_argument, 0, "exec the specified assembly just before app loading", uwsgi_opt_add_string_list, &umono.exec, 0},
|
||||
{"mono-index", required_argument, 0, "add an asp.net index file", uwsgi_opt_add_string_list, &umono.index, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static MonoString *uwsgi_mono_method_GetFilePath(MonoObject *this) {
|
||||
|
||||
@@ -374,7 +374,7 @@ PHP_FUNCTION(uwsgi_rpc) {
|
||||
zval *z_current_obj;
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
uint16_t size = 0;
|
||||
uint64_t size = 0;
|
||||
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &varargs, &num_args) == FAILURE) {
|
||||
RETURN_NULL();
|
||||
|
||||
@@ -53,6 +53,16 @@ struct uwsgi_perl {
|
||||
|
||||
struct uwsgi_string_list *exec;
|
||||
struct uwsgi_string_list *exec_post_fork;
|
||||
|
||||
int auto_reload;
|
||||
time_t last_auto_reload;
|
||||
struct uwsgi_string_list *auto_reload_ignore;
|
||||
HV *auto_reload_hash;
|
||||
|
||||
int enable_psgix_io;
|
||||
|
||||
char *shell;
|
||||
int shell_oneshot;
|
||||
};
|
||||
|
||||
void init_perl_embedded_module(void);
|
||||
@@ -70,3 +80,5 @@ PerlInterpreter *uwsgi_perl_new_interpreter(void);
|
||||
int uwsgi_perl_mule(char *);
|
||||
void uwsgi_perl_run_hook(SV *);
|
||||
void uwsgi_perl_exec(char *);
|
||||
|
||||
void uwsgi_perl_check_auto_reload(void);
|
||||
|
||||
@@ -260,7 +260,6 @@ static void uwsgi_perl_free_stashes(void) {
|
||||
|
||||
int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, PerlInterpreter **interpreters) {
|
||||
|
||||
struct stat st;
|
||||
int i;
|
||||
SV **callables;
|
||||
|
||||
@@ -268,31 +267,14 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
|
||||
|
||||
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;
|
||||
}
|
||||
size_t size;
|
||||
char *buf = uwsgi_open_and_read(app_name, &size, 1, NULL);
|
||||
|
||||
if (fstat(fd, &st)) {
|
||||
uwsgi_error("fstat()");
|
||||
close(fd);
|
||||
goto clear2;
|
||||
if (uwsgi_file_exists(app_name)) {
|
||||
// prepare for $0 (if the file is local)
|
||||
uperl.embedding[1] = app_name;
|
||||
}
|
||||
|
||||
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) {
|
||||
@@ -309,10 +291,7 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
|
||||
}
|
||||
}
|
||||
|
||||
if (!interpreters) {
|
||||
goto clear2;
|
||||
}
|
||||
|
||||
if (!interpreters) goto clear2;
|
||||
|
||||
callables = uwsgi_calloc(sizeof(SV *) * uwsgi.threads);
|
||||
uperl.tmp_streaming_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
|
||||
@@ -370,6 +349,7 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
|
||||
|
||||
perl_eval_pv("use IO::Handle;", 0);
|
||||
perl_eval_pv("use IO::File;", 0);
|
||||
perl_eval_pv("use IO::Socket;", 0);
|
||||
perl_eval_pv("use Scalar::Util;", 0);
|
||||
if (!uperl.no_die_catch) {
|
||||
perl_eval_pv("use Devel::StackTrace;", 0);
|
||||
@@ -483,7 +463,7 @@ void uwsgi_psgi_app() {
|
||||
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
|
||||
}
|
||||
// create a perl environment (if needed)
|
||||
else if (uperl.exec) {
|
||||
else if (uperl.exec || uperl.shell) {
|
||||
PERL_SET_CONTEXT(uperl.main[0]);
|
||||
perl_parse(uperl.main[0], xs_init, 2, uperl.embedding, NULL);
|
||||
}
|
||||
|
||||
+154
-6
@@ -11,9 +11,25 @@ struct uwsgi_perl uperl;
|
||||
|
||||
struct uwsgi_plugin psgi_plugin;
|
||||
|
||||
static void uwsgi_opt_plshell(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi.honour_stdin = 1;
|
||||
if (value) {
|
||||
uperl.shell = value;
|
||||
}
|
||||
else {
|
||||
uperl.shell = "";
|
||||
}
|
||||
|
||||
if (!strcmp("plshell-oneshot", opt)) {
|
||||
uperl.shell_oneshot = 1;
|
||||
}
|
||||
}
|
||||
|
||||
struct uwsgi_option uwsgi_perl_options[] = {
|
||||
|
||||
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
|
||||
{"psgi-enable-psgix-io", no_argument, 0, "enable psgix.io support", uwsgi_opt_true, &uperl.enable_psgix_io, 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},
|
||||
#ifdef PERL_VERSION_STRING
|
||||
@@ -23,10 +39,63 @@ struct uwsgi_option uwsgi_perl_options[] = {
|
||||
{"perl-arg", required_argument, 0, "add an item to @ARGV", uwsgi_opt_add_string_list, &uperl.argv_item, 0},
|
||||
{"perl-exec", required_argument, 0, "exec the specified perl file before fork()", uwsgi_opt_add_string_list, &uperl.exec, 0},
|
||||
{"perl-exec-post-fork", required_argument, 0, "exec the specified perl file after fork()", uwsgi_opt_add_string_list, &uperl.exec_post_fork, 0},
|
||||
{"perl-auto-reload", required_argument, 0, "enable perl auto-reloader with the specified frequency", uwsgi_opt_set_int, &uperl.auto_reload, UWSGI_OPT_MASTER},
|
||||
{"perl-auto-reload-ignore", required_argument, 0, "ignore the specified files when auto-reload is enabled", uwsgi_opt_add_string_list, &uperl.auto_reload_ignore, UWSGI_OPT_MASTER},
|
||||
|
||||
{"plshell", optional_argument, 0, "run a perl interactive shell", uwsgi_opt_plshell, NULL, 0},
|
||||
{"plshell-oneshot", no_argument, 0, "run a perl interactive shell (one shot)", uwsgi_opt_plshell, NULL, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
|
||||
int uwsgi_perl_check_mtime(time_t now, HV *list, SV *key) {
|
||||
// insert item with the current time
|
||||
if (!hv_exists_ent(list, key, 0)) {
|
||||
// useless if...
|
||||
if (hv_store_ent(list, key, newSViv(now), 0)) return 0;
|
||||
}
|
||||
else {
|
||||
// compare mtime
|
||||
struct stat st;
|
||||
if (stat(SvPV_nolen(key), &st)) return 0;
|
||||
HE *mtime = hv_fetch_ent(list, key, 0, 0);
|
||||
if (!mtime) return 0;
|
||||
if (st.st_mtime > SvIV(HeVAL(mtime))) {
|
||||
uwsgi_log_verbose("[perl-auto-reloader] %s has been modified !!!\n", SvPV_nolen(key));
|
||||
kill(uwsgi.workers[0].pid, SIGHUP);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void uwsgi_perl_check_auto_reload() {
|
||||
time_t now = uwsgi_now();
|
||||
HE *he;
|
||||
if (!uperl.auto_reload_hash) {
|
||||
uperl.auto_reload_hash = newHV();
|
||||
// useless return value
|
||||
if (!SvREFCNT_inc(uperl.auto_reload_hash)) return;
|
||||
}
|
||||
GV *gv_inc = gv_fetchpv("INC", TRUE, SVt_PV);
|
||||
if (!gv_inc) return;
|
||||
HV *inc = GvHV(gv_inc);
|
||||
hv_iterinit(inc);
|
||||
while((he = hv_iternext(inc))) {
|
||||
SV *filename = hv_iterval(inc, he);
|
||||
struct uwsgi_string_list *usl;
|
||||
int found = 0;
|
||||
uwsgi_foreach(usl, uperl.auto_reload_ignore) {
|
||||
if (!strcmp(usl->value, SvPV_nolen(filename))) {
|
||||
found = 1; break;
|
||||
}
|
||||
}
|
||||
if (found) continue;
|
||||
if (uwsgi_perl_check_mtime(now, uperl.auto_reload_hash, filename)) return;
|
||||
}
|
||||
}
|
||||
|
||||
SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
|
||||
SV *newobj;
|
||||
@@ -52,6 +121,31 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
|
||||
|
||||
}
|
||||
|
||||
SV *uwsgi_perl_obj_new_from_fd(char *class, size_t class_len, int fd) {
|
||||
SV *newobj;
|
||||
|
||||
dSP;
|
||||
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(sv_2mortal(newSVpv( class, class_len)));
|
||||
XPUSHs(sv_2mortal(newSViv( fd )));
|
||||
XPUSHs(sv_2mortal(newSVpv( "w", 1 )));
|
||||
PUTBACK;
|
||||
|
||||
call_method( "new_from_fd", G_SCALAR);
|
||||
|
||||
SPAGAIN;
|
||||
|
||||
newobj = SvREFCNT_inc(POPs);
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
return newobj;
|
||||
}
|
||||
|
||||
SV *uwsgi_perl_call_stream(SV *func) {
|
||||
|
||||
SV *ret = NULL;
|
||||
@@ -195,7 +289,10 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
ret = (AV *) SvREFCNT_inc(SvRV(POPs));
|
||||
SV *r = POPs;
|
||||
if (SvROK(r)) {
|
||||
ret = (AV *) SvREFCNT_inc(SvRV(r));
|
||||
}
|
||||
}
|
||||
|
||||
PUTBACK;
|
||||
@@ -310,7 +407,12 @@ SV *build_psgi_env(struct wsgi_request *wsgi_req) {
|
||||
// cleanup handlers array
|
||||
av = newAV();
|
||||
if (!hv_store(env, "psgix.cleanup.handlers", 22, newRV_noinc((SV *)av ), 0)) goto clear;
|
||||
|
||||
|
||||
// this call requires a bunch of syscalls, so it hurts performance
|
||||
if (uperl.enable_psgix_io) {
|
||||
SV *io = uwsgi_perl_obj_new_from_fd("IO::Socket", 10, wsgi_req->fd);
|
||||
if (!hv_store(env, "psgix.io", 8, io, 0)) goto clear;
|
||||
}
|
||||
|
||||
SV *pe = uwsgi_perl_obj_new("uwsgi::error", 12);
|
||||
if (!hv_store(env, "psgi.errors", 11, pe, 0)) goto clear;
|
||||
@@ -563,6 +665,14 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
|
||||
// clear the env
|
||||
SvREFCNT_dec(wsgi_req->async_environ);
|
||||
|
||||
// now we can check for changed files
|
||||
if (uperl.auto_reload) {
|
||||
time_t now = uwsgi_now();
|
||||
if (now - uperl.last_auto_reload > uperl.auto_reload) {
|
||||
uwsgi_perl_check_auto_reload();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_perl_magic(char *mountpoint, char *lazy) {
|
||||
@@ -706,10 +816,10 @@ realstuff:
|
||||
}
|
||||
}
|
||||
|
||||
static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
static uint64_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
|
||||
|
||||
int i;
|
||||
uint16_t ret = 0;
|
||||
uint64_t ret = 0;
|
||||
|
||||
dSP;
|
||||
ENTER;
|
||||
@@ -730,8 +840,11 @@ static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t a
|
||||
STRLEN rlen;
|
||||
SV *response = POPs;
|
||||
char *value = SvPV(response, rlen );
|
||||
ret = UMIN(UMAX16-1, rlen);
|
||||
memcpy(buffer, value, ret);
|
||||
if (rlen > 0) {
|
||||
*buffer = uwsgi_malloc(rlen);
|
||||
memcpy(*buffer, value, rlen);
|
||||
ret = rlen;
|
||||
}
|
||||
}
|
||||
|
||||
PUTBACK;
|
||||
@@ -741,6 +854,39 @@ static uint16_t uwsgi_perl_rpc(void *func, uint8_t argc, char **argv, uint16_t a
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uwsgi_perl_hijack(void) {
|
||||
if (uperl.shell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 0;
|
||||
return;
|
||||
}
|
||||
if (uperl.shell && uwsgi.mywid == 1) {
|
||||
uwsgi.workers[uwsgi.mywid].hijacked = 1;
|
||||
uwsgi.workers[uwsgi.mywid].hijacked_count++;
|
||||
// re-map stdin to stdout and stderr if we are logging to a file
|
||||
if (uwsgi.logfile) {
|
||||
if (dup2(0, 1) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
if (dup2(0, 2) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
}
|
||||
|
||||
if (uperl.shell[0] != 0) {
|
||||
perl_eval_pv(uperl.shell, 0);
|
||||
}
|
||||
else {
|
||||
perl_eval_pv("use Devel::REPL;my $repl = Devel::REPL->new;$repl->run;", 0);
|
||||
}
|
||||
if (uperl.shell_oneshot) {
|
||||
exit(UWSGI_DE_HIJACKED_CODE);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin psgi_plugin = {
|
||||
|
||||
.name = "psgi",
|
||||
@@ -757,6 +903,8 @@ struct uwsgi_plugin psgi_plugin = {
|
||||
|
||||
.mule = uwsgi_perl_mule,
|
||||
|
||||
.hijack_worker = uwsgi_perl_hijack,
|
||||
|
||||
.post_fork = uwsgi_perl_post_fork,
|
||||
.request = uwsgi_perl_request,
|
||||
.after_request = uwsgi_perl_after_request,
|
||||
|
||||
@@ -76,10 +76,20 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
if (!headers) { uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;}
|
||||
|
||||
// generate headers
|
||||
for(i=0; i<=av_len(headers); i++) {
|
||||
int headers_len = (int) av_len(headers);
|
||||
for(i=0; i<=headers_len; i++) {
|
||||
hitem = av_fetch(headers,i,0);
|
||||
if (!*hitem) {
|
||||
uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;
|
||||
}
|
||||
chitem = SvPV(*hitem, hlen);
|
||||
if (i+1 > headers_len) {
|
||||
uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;
|
||||
}
|
||||
hitem = av_fetch(headers,i+1,0);
|
||||
if (!*hitem) {
|
||||
uwsgi_log("invalid PSGI headers\n"); return UWSGI_OK;
|
||||
}
|
||||
chitem2 = SvPV(*hitem, hlen2);
|
||||
if (uwsgi_response_add_header(wsgi_req, chitem, hlen, chitem2, hlen2)) return UWSGI_OK;
|
||||
i++;
|
||||
|
||||
@@ -324,7 +324,7 @@ XS(XS_call) {
|
||||
dXSARGS;
|
||||
|
||||
char *func;
|
||||
uint16_t size = 0;
|
||||
uint64_t size = 0;
|
||||
int i;
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
@@ -351,6 +351,41 @@ XS(XS_call) {
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_rpc) {
|
||||
|
||||
dXSARGS;
|
||||
|
||||
char *node;
|
||||
char *func;
|
||||
uint64_t size = 0;
|
||||
int i;
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
STRLEN arg_len;
|
||||
|
||||
psgi_check_args(2);
|
||||
|
||||
node = SvPV_nolen(ST(0));
|
||||
func = SvPV_nolen(ST(1));
|
||||
|
||||
for(i=0;i<(items-2);i++) {
|
||||
argv[i] = SvPV(ST(i+2), arg_len);
|
||||
argvs[i] = arg_len;
|
||||
}
|
||||
|
||||
// response must be always freed
|
||||
char *response = uwsgi_do_rpc(node, func, items-2, argv, argvs, &size);
|
||||
if (response) {
|
||||
ST(0) = newSVpv(response, size);
|
||||
sv_2mortal(ST(0));
|
||||
free(response);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
XS(XS_suspend) {
|
||||
|
||||
@@ -404,9 +439,20 @@ XS(XS_i_am_the_lord) {
|
||||
}
|
||||
XSRETURN_NO;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
XS(XS_connection_fd) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(0);
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
ST(0) = newSViv(wsgi_req->fd);
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_websocket_handshake) {
|
||||
|
||||
dXSARGS;
|
||||
@@ -524,7 +570,143 @@ XS(XS_add_rb_timer) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_metric_inc) {
|
||||
dXSARGS;
|
||||
char *metric = NULL;
|
||||
STRLEN metric_len = 0;
|
||||
int64_t value = 1;
|
||||
psgi_check_args(1);
|
||||
metric = SvPV(ST(0), metric_len);
|
||||
if (items > 1) {
|
||||
value = (int64_t) SvIV(ST(1));
|
||||
}
|
||||
if (uwsgi_metric_inc(metric, NULL, value)) {
|
||||
croak("unable to update metric");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
XS(XS_metric_dec) {
|
||||
dXSARGS;
|
||||
char *metric = NULL;
|
||||
STRLEN metric_len = 0;
|
||||
int64_t value = 1;
|
||||
psgi_check_args(1);
|
||||
metric = SvPV(ST(0), metric_len);
|
||||
if (items > 1) {
|
||||
value = (int64_t) SvIV(ST(1));
|
||||
}
|
||||
if (uwsgi_metric_dec(metric, NULL, value)) {
|
||||
croak("unable to update metric");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
XS(XS_metric_mul) {
|
||||
dXSARGS;
|
||||
char *metric = NULL;
|
||||
STRLEN metric_len = 0;
|
||||
int64_t value = 1;
|
||||
psgi_check_args(1);
|
||||
metric = SvPV(ST(0), metric_len);
|
||||
if (items > 1) {
|
||||
value = (int64_t) SvIV(ST(1));
|
||||
}
|
||||
if (uwsgi_metric_mul(metric, NULL, value)) {
|
||||
croak("unable to update metric");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
XS(XS_metric_div) {
|
||||
dXSARGS;
|
||||
char *metric = NULL;
|
||||
STRLEN metric_len = 0;
|
||||
int64_t value = 1;
|
||||
psgi_check_args(1);
|
||||
metric = SvPV(ST(0), metric_len);
|
||||
if (items > 1) {
|
||||
value = (int64_t) SvIV(ST(1));
|
||||
}
|
||||
if (uwsgi_metric_div(metric, NULL, value)) {
|
||||
croak("unable to update metric");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
XS(XS_metric_set) {
|
||||
dXSARGS;
|
||||
char *metric = NULL;
|
||||
STRLEN metric_len = 0;
|
||||
int64_t value = 0;
|
||||
psgi_check_args(2);
|
||||
metric = SvPV(ST(0), metric_len);
|
||||
value = (int64_t) SvIV(ST(1));
|
||||
if (uwsgi_metric_set(metric, NULL, value)) {
|
||||
croak("unable to update metric");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
XS(XS_metric_get) {
|
||||
dXSARGS;
|
||||
|
||||
char *metric = NULL;
|
||||
STRLEN metric_len = 0;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
metric = SvPV(ST(0), metric_len);
|
||||
|
||||
ST(0) = newSViv(uwsgi_metric_get(metric, NULL));
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_chunked_read) {
|
||||
dXSARGS;
|
||||
int timeout = 0;
|
||||
size_t len = 0;
|
||||
|
||||
psgi_check_args(0);
|
||||
if (items > 0) {
|
||||
timeout = SvIV(ST(0));
|
||||
}
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
char *chunk = uwsgi_chunked_read(wsgi_req, &len, timeout, 0);
|
||||
if (!chunk) {
|
||||
croak("unable to receive chunked part");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
ST(0) = newSVpv(chunk, len);
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_chunked_read_nb) {
|
||||
dXSARGS;
|
||||
size_t len = 0;
|
||||
|
||||
psgi_check_args(0);
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
char *chunk = uwsgi_chunked_read(wsgi_req, &len, 0, 1);
|
||||
if (!chunk) {
|
||||
if (uwsgi_is_again()) XSRETURN_UNDEF;
|
||||
croak("unable to receive chunked part");
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
ST(0) = newSVpv(chunk, len);
|
||||
sv_2mortal(ST(0));
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
void init_perl_embedded_module() {
|
||||
psgi_xs(reload);
|
||||
@@ -536,6 +718,7 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(cache_clear);
|
||||
|
||||
psgi_xs(call);
|
||||
psgi_xs(rpc);
|
||||
psgi_xs(wait_fd_read);
|
||||
psgi_xs(wait_fd_write);
|
||||
psgi_xs(async_sleep);
|
||||
@@ -549,6 +732,9 @@ void init_perl_embedded_module() {
|
||||
#ifdef UWSGI_SSL
|
||||
psgi_xs(i_am_the_lord);
|
||||
#endif
|
||||
|
||||
psgi_xs(connection_fd);
|
||||
|
||||
psgi_xs(alarm);
|
||||
psgi_xs(websocket_handshake);
|
||||
psgi_xs(websocket_recv);
|
||||
@@ -561,5 +747,15 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(add_rb_timer);
|
||||
|
||||
psgi_xs(set_user_harakiri);
|
||||
|
||||
psgi_xs(metric_inc);
|
||||
psgi_xs(metric_dec);
|
||||
psgi_xs(metric_mul);
|
||||
psgi_xs(metric_div);
|
||||
psgi_xs(metric_get);
|
||||
psgi_xs(metric_set);
|
||||
|
||||
psgi_xs(chunked_read);
|
||||
psgi_xs(chunked_read_nb);
|
||||
}
|
||||
|
||||
|
||||
+52
-8
@@ -1,7 +1,7 @@
|
||||
#include <uwsgi.h>
|
||||
#ifdef __linux__
|
||||
#if defined(__linux__) || defined(__GNU_kFreeBSD__)
|
||||
#include <pty.h>
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__)
|
||||
#elif defined(__APPLE__) || defined(__OpenBSD__) || defined(__NetBSD__)
|
||||
#include <util.h>
|
||||
#elif defined(__FreeBSD__)
|
||||
#include <libutil.h>
|
||||
@@ -21,6 +21,7 @@ struct uwsgi_pty_client {
|
||||
static struct uwsgi_pty {
|
||||
char *addr;
|
||||
char *remote;
|
||||
char *uremote;
|
||||
int queue;
|
||||
int server_fd;
|
||||
int master_fd;
|
||||
@@ -76,7 +77,8 @@ static struct uwsgi_option uwsgi_pty_options[] = {
|
||||
{"pty-socket", required_argument, 0, "bind the pty server on the specified address", uwsgi_opt_set_str, &upty.addr, 0},
|
||||
{"pty-log", no_argument, 0, "send stdout/stderr to the log engine too", uwsgi_opt_true, &upty.log, 0},
|
||||
{"pty-input", no_argument, 0, "read from original stdin in addition to pty", uwsgi_opt_true, &upty.input, 0},
|
||||
{"pty-connect", required_argument, 0, "connect the current terminal to a pty server", uwsgi_opt_set_str, &upty.remote, 0},
|
||||
{"pty-connect", required_argument, 0, "connect the current terminal to a pty server", uwsgi_opt_set_str, &upty.remote, UWSGI_OPT_NO_INITIAL},
|
||||
{"pty-uconnect", required_argument, 0, "connect the current terminal to a pty server (using uwsgi protocol)", uwsgi_opt_set_str, &upty.uremote, UWSGI_OPT_NO_INITIAL},
|
||||
{"pty-no-isig", no_argument, 0, "disable ISIG terminal attribute in client mode", uwsgi_opt_true, &upty.no_isig, 0},
|
||||
{"pty-exec", required_argument, 0, "run the specified command soon after the pty thread is spawned", uwsgi_opt_set_str, &upty.command, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
@@ -147,6 +149,7 @@ static void *uwsgi_pty_loop(void *arg) {
|
||||
if (rlen == 0) exit(1);
|
||||
if (rlen < 0) {
|
||||
uwsgi_error("uwsgi_pty_loop()/read()");
|
||||
continue;
|
||||
}
|
||||
if (upty.log && upty.original_log >= 0) {
|
||||
if (write(upty.original_log, buf, rlen) != rlen) {
|
||||
@@ -256,17 +259,40 @@ static void uwsgi_pty_init() {
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_pty_client() {
|
||||
if (!upty.remote) return 0;
|
||||
static void uwsgi_pty_winch() {
|
||||
// 2 uwsgi packets
|
||||
char uwsgi_pkt[8];
|
||||
#ifdef TIOCGWINSZ
|
||||
struct winsize w;
|
||||
ioctl(0, TIOCGWINSZ, &w);
|
||||
uwsgi_pkt[0] = 0;
|
||||
uwsgi_pkt[1] = (uint8_t) (w.ws_row & 0xff);
|
||||
uwsgi_pkt[2] = (uint8_t) ((w.ws_row >> 8) & 0xff);
|
||||
uwsgi_pkt[3] = 100;
|
||||
uwsgi_pkt[4] = 0;
|
||||
uwsgi_pkt[5] = (uint8_t) (w.ws_col & 0xff);
|
||||
uwsgi_pkt[6] = (uint8_t) ((w.ws_col >> 8) & 0xff);
|
||||
uwsgi_pkt[7] = 101;
|
||||
#endif
|
||||
if (write(upty.server_fd, uwsgi_pkt, 8) != 8) {
|
||||
uwsgi_error("uwsgi_pty_winch()/write()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("[pty] connecting to %s ...\n", upty.remote);
|
||||
static int uwsgi_pty_client() {
|
||||
if (!upty.remote && !upty.uremote) return 0;
|
||||
|
||||
char *remote = upty.uremote ? upty.uremote : upty.remote;
|
||||
|
||||
uwsgi_log("[pty] connecting to %s ...\n", remote);
|
||||
|
||||
// save current terminal settings
|
||||
if (!tcgetattr(0, &uwsgi.termios)) {
|
||||
uwsgi.restore_tc = 1;
|
||||
}
|
||||
|
||||
upty.server_fd = uwsgi_connect(upty.remote, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
upty.server_fd = uwsgi_connect(remote, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
|
||||
if (upty.server_fd < 0) {
|
||||
uwsgi_error("uwsgi_pty_client()/connect()");
|
||||
exit(1);
|
||||
@@ -277,8 +303,15 @@ static int uwsgi_pty_client() {
|
||||
|
||||
uwsgi_log("[pty] connected.\n");
|
||||
|
||||
|
||||
uwsgi_pty_setterm(0);
|
||||
|
||||
if (upty.uremote) {
|
||||
signal(SIGWINCH, uwsgi_pty_winch);
|
||||
// send current terminal size
|
||||
uwsgi_pty_winch();
|
||||
}
|
||||
|
||||
upty.queue = event_queue_init();
|
||||
event_queue_add_fd_read(upty.queue, upty.server_fd);
|
||||
event_queue_add_fd_read(upty.queue, 0);
|
||||
@@ -287,10 +320,21 @@ static int uwsgi_pty_client() {
|
||||
char buf[8192];
|
||||
int interesting_fd = -1;
|
||||
int ret = event_queue_wait(upty.queue, -1, &interesting_fd);
|
||||
if (ret <= 0) break;
|
||||
if (ret == 0) break;
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR) continue;
|
||||
break;
|
||||
}
|
||||
if (interesting_fd == 0) {
|
||||
ssize_t rlen = read(0, buf, 8192);
|
||||
if (rlen <= 0) break;
|
||||
if (upty.uremote) {
|
||||
struct uwsgi_header uh;
|
||||
uh.modifier1 = 0;
|
||||
uh.pktsize = rlen;
|
||||
uh.modifier2 = 0;
|
||||
if (write(upty.server_fd, &uh, 4) != 4) break;
|
||||
}
|
||||
if (write(upty.server_fd, buf, rlen) != rlen) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -274,10 +274,10 @@ static int uwsgi_pypy_signal_handler(uint8_t sig, void *handler) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint16_t uwsgi_pypy_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
static uint64_t uwsgi_pypy_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
|
||||
int iargvs[UMAX8];
|
||||
int i;
|
||||
int (*pypy_func)(int, char **, int*, char *) = (int (*)(int, char **, int*, char *)) func;
|
||||
int (*pypy_func)(int, char **, int*, char **) = (int (*)(int, char **, int*, char **)) func;
|
||||
// we convert 16bit to int
|
||||
for(i=0;i<argc;i++) {
|
||||
iargvs[i] = (int) argvs[i];
|
||||
@@ -313,6 +313,7 @@ static void uwsgi_pypy_onload() {
|
||||
#ifdef UWSGI_PYPY_HOME
|
||||
upypy.home = UWSGI_PYPY_HOME;
|
||||
#endif
|
||||
uwsgi.has_threads = 1;
|
||||
}
|
||||
|
||||
static int uwsgi_pypy_mule(char *opt) {
|
||||
|
||||
@@ -172,6 +172,8 @@ const char *uwsgi_pypy_version;
|
||||
|
||||
char *uwsgi_binary_path();
|
||||
|
||||
void *uwsgi_malloc(size_t);
|
||||
|
||||
int uwsgi_response_prepare_headers(struct wsgi_request *, char *, size_t);
|
||||
int uwsgi_response_add_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
int uwsgi_response_write_body_do(struct wsgi_request *, char *, size_t);
|
||||
@@ -186,7 +188,7 @@ int uwsgi_is_again();
|
||||
int uwsgi_register_rpc(char *, struct uwsgi_plugin *, uint8_t, void *);
|
||||
int uwsgi_register_signal(uint8_t, char *, void *, uint8_t);
|
||||
|
||||
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
|
||||
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint64_t *);
|
||||
|
||||
void uwsgi_set_processname(char *);
|
||||
int uwsgi_signal_send(int, uint8_t);
|
||||
@@ -235,6 +237,13 @@ int uwsgi_ready_fd(struct wsgi_request *);
|
||||
|
||||
void set_user_harakiri(int);
|
||||
|
||||
int uwsgi_metric_set(char *, char *, int64_t);
|
||||
int uwsgi_metric_inc(char *, char *, int64_t);
|
||||
int uwsgi_metric_dec(char *, char *, int64_t);
|
||||
int uwsgi_metric_mul(char *, char *, int64_t);
|
||||
int uwsgi_metric_div(char *, char *, int64_t);
|
||||
int64_t uwsgi_metric_get(char *, char *);
|
||||
|
||||
%s
|
||||
|
||||
''' % ('\n'.join(uwsgi_cdef), hooks)
|
||||
@@ -483,15 +492,16 @@ class uwsgi_pypy_RPC(object):
|
||||
for i in range(0, argc):
|
||||
pargs.append(ffi.string(argv[i], argvs[i]))
|
||||
response = self.func(*pargs)
|
||||
if len(response) > 0 and len(response) <= 65535:
|
||||
dst = ffi.buffer(buf, 65536)
|
||||
if len(response) > 0:
|
||||
buf[0] = lib.uwsgi_malloc(len(response))
|
||||
dst = ffi.buffer(buf[0], len(response))
|
||||
dst[:len(response)] = response
|
||||
return len(response)
|
||||
|
||||
|
||||
def uwsgi_pypy_uwsgi_register_rpc(name, func, argc=0):
|
||||
rpc_func = uwsgi_pypy_RPC(func)
|
||||
cb = ffi.callback("int(int, char*[], int[], char*)", rpc_func)
|
||||
cb = ffi.callback("int(int, char*[], int[], char**)", rpc_func)
|
||||
uwsgi_gc.append(cb)
|
||||
if lib.uwsgi_register_rpc(ffi.new("char[]", name), ffi.addressof(lib.pypy_plugin), argc, cb) < 0:
|
||||
raise Exception("unable to register rpc func %s" % name)
|
||||
@@ -501,7 +511,7 @@ def uwsgi_pypy_rpc(node, func, *args):
|
||||
argc = 0
|
||||
argv = ffi.new('char*[256]')
|
||||
argvs = ffi.new('uint16_t[256]')
|
||||
rsize = ffi.new('uint16_t*')
|
||||
rsize = ffi.new('uint64_t*')
|
||||
|
||||
for arg in args:
|
||||
if argc >= 255:
|
||||
@@ -534,6 +544,12 @@ uwsgi.call = uwsgi_pypy_call
|
||||
|
||||
uwsgi.signal = lambda x: lib.uwsgi_signal_send(lib.uwsgi.signal_socket, x)
|
||||
|
||||
uwsgi.metric_get = lambda x: lib.uwsgi_metric_get(x, ffi.NULL)
|
||||
uwsgi.metric_set = lambda x, y: lib.uwsgi_metric_set(x, ffi.NULL, y)
|
||||
uwsgi.metric_inc = lambda x, y=1: lib.uwsgi_metric_inc(x, ffi.NULL, y)
|
||||
uwsgi.metric_dec = lambda x, y=1: lib.uwsgi_metric_dec(x, ffi.NULL, y)
|
||||
uwsgi.metric_mul = lambda x, y=1: lib.uwsgi_metric_mul(x, ffi.NULL, y)
|
||||
uwsgi.metric_div = lambda x, y=1: lib.uwsgi_metric_div(x, ffi.NULL, y)
|
||||
|
||||
def uwsgi_pypy_uwsgi_cache_get(key, cache=ffi.NULL):
|
||||
vallen = ffi.new('uint64_t*')
|
||||
|
||||
@@ -167,7 +167,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
PyThreadState_Swap(wi->interpreter);
|
||||
init_pyargv();
|
||||
|
||||
// we need to inizialize an embedded module for every interpreter
|
||||
// we need to initialize an embedded module for every interpreter
|
||||
init_uwsgi_embedded_module();
|
||||
init_uwsgi_vars();
|
||||
|
||||
@@ -205,7 +205,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
app_list = PyDict_Keys(applications);
|
||||
multiapp = PyList_Size(app_list);
|
||||
if (multiapp < 1) {
|
||||
uwsgi_log("you have to define at least one app in the apllications dictionary\n");
|
||||
uwsgi_log("you have to define at least one app in the applications dictionary\n");
|
||||
goto doh;
|
||||
}
|
||||
|
||||
@@ -227,6 +227,10 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
PyObject *callables_dict = get_uwsgi_pydict((char *)arg1);
|
||||
if (callables_dict) {
|
||||
wi->callable = PyDict_GetItem(callables_dict, (PyObject *)wi->callable);
|
||||
if (!wi->callable) {
|
||||
uwsgi_log("skipping broken app %s\n", wsgi_req->appid);
|
||||
goto multiapp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -336,9 +340,11 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
|
||||
const char *default_app = "";
|
||||
|
||||
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
|
||||
default_app = " (default app)" ;
|
||||
uwsgi.default_app = id;
|
||||
if (!uwsgi.no_default_app) {
|
||||
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
|
||||
default_app = " (default app)" ;
|
||||
uwsgi.default_app = id;
|
||||
}
|
||||
}
|
||||
|
||||
wi->started_at = now;
|
||||
@@ -357,6 +363,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
|
||||
uwsgi_apps_cnt++;
|
||||
|
||||
multiapp:
|
||||
if (multiapp > 1) {
|
||||
for(i=1;i<multiapp;i++) {
|
||||
PyObject *app_mnt = PyList_GetItem(app_list, i);
|
||||
|
||||
@@ -156,8 +156,14 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"wsgi-env-behavior", required_argument, 0, "set the strategy for allocating/deallocating the WSGI env", uwsgi_opt_set_str, &up.wsgi_env_behaviour, 0},
|
||||
{"start_response-nodelay", no_argument, 0, "send WSGI http headers as soon as possible (PEP violation)", uwsgi_opt_true, &up.start_response_nodelay, 0},
|
||||
|
||||
{"wsgi-strict", no_argument, 0, "try to be fully PEP compliant disabling optimizations", uwsgi_opt_true, &up.wsgi_strict, 0},
|
||||
{"wsgi-accept-buffer", no_argument, 0, "accept CPython buffer-compliant objects as WSGI response in addition to string/bytes", uwsgi_opt_true, &up.wsgi_accept_buffer, 0},
|
||||
{"wsgi-accept-buffers", no_argument, 0, "accept CPython buffer-compliant objects as WSGI response in addition to string/bytes", uwsgi_opt_true, &up.wsgi_accept_buffer, 0},
|
||||
|
||||
{"python-version", no_argument, 0, "report python version", uwsgi_opt_pyver, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"python-raw", required_argument, 0, "load a python file for managing raw requests", uwsgi_opt_set_str, &up.raw, 0},
|
||||
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
};
|
||||
|
||||
@@ -308,6 +314,10 @@ realstuff:
|
||||
// this time we use this higher level function
|
||||
// as this code can be executed in a signal handler
|
||||
|
||||
#ifdef __GNU_kFreeBSD__
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (!Py_IsInitialized()) {
|
||||
return;
|
||||
}
|
||||
@@ -1068,7 +1078,6 @@ void uwsgi_python_init_apps() {
|
||||
up.loaders[LOADER_CALLABLE] = uwsgi_callable_loader;
|
||||
up.loaders[LOADER_STRING_CALLABLE] = uwsgi_string_callable_loader;
|
||||
|
||||
|
||||
struct uwsgi_string_list *upli = up.import_list;
|
||||
while(upli) {
|
||||
if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) {
|
||||
@@ -1119,6 +1128,12 @@ next:
|
||||
uppa = uppa->next;
|
||||
}
|
||||
|
||||
if (up.raw) {
|
||||
up.raw_callable = uwsgi_file_loader(up.raw);
|
||||
if (up.raw_callable) {
|
||||
Py_INCREF(up.raw_callable);
|
||||
}
|
||||
}
|
||||
|
||||
if (up.wsgi_config != NULL) {
|
||||
init_uwsgi_app(LOADER_UWSGI, up.wsgi_config, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
|
||||
@@ -1354,8 +1369,10 @@ void *uwsgi_python_autoreloader_thread(void *foobar) {
|
||||
UWSGI_RELEASE_GIL;
|
||||
sleep(up.auto_reload);
|
||||
UWSGI_GET_GIL;
|
||||
// do not start monitoring til the first app is loaded (required for lazy mode)
|
||||
if (uwsgi_apps_cnt == 0) continue;
|
||||
if (uwsgi.lazy || uwsgi.lazy_apps) {
|
||||
// do not start monitoring til the first app is loaded (required for lazy mode)
|
||||
if (uwsgi_apps_cnt == 0) continue;
|
||||
}
|
||||
#ifdef UWSGI_PYTHON_OLD
|
||||
int pos = 0;
|
||||
#else
|
||||
@@ -1363,6 +1380,7 @@ void *uwsgi_python_autoreloader_thread(void *foobar) {
|
||||
#endif
|
||||
PyObject *mod_name, *mod;
|
||||
while (PyDict_Next(modules, &pos, &mod_name, &mod)) {
|
||||
if (mod == NULL) continue;
|
||||
int found = 0;
|
||||
struct uwsgi_string_list *usl = up.auto_reload_ignore;
|
||||
while(usl) {
|
||||
@@ -1504,7 +1522,7 @@ clear:
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
uint64_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
|
||||
|
||||
UWSGI_GET_GIL;
|
||||
|
||||
@@ -1528,8 +1546,9 @@ uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[
|
||||
if (PyString_Check(ret)) {
|
||||
rv = PyString_AsString(ret);
|
||||
rl = PyString_Size(ret);
|
||||
if (rl <= 65536) {
|
||||
memcpy(buffer, rv, rl);
|
||||
if (rl > 0) {
|
||||
*buffer = uwsgi_malloc(rl);
|
||||
memcpy(*buffer, rv, rl);
|
||||
Py_DECREF(ret);
|
||||
UWSGI_RELEASE_GIL;
|
||||
return rl;
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
#include "uwsgi_python.h"
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
extern struct uwsgi_python up;
|
||||
|
||||
static int manage_raw_response(struct wsgi_request *wsgi_req) {
|
||||
int ret = 0;
|
||||
if (!wsgi_req->async_force_again) {
|
||||
ret = uwsgi_python_send_body(wsgi_req, (PyObject *) wsgi_req->async_result);
|
||||
if (ret == 0) {
|
||||
if (PyInt_Check((PyObject *) wsgi_req->async_result) || PyObject_HasAttrString((PyObject *) wsgi_req->async_result, "fileno")) {
|
||||
// is it a file ?
|
||||
int fd = PyObject_AsFileDescriptor((PyObject *) wsgi_req->async_result);
|
||||
if (fd >= 0) {
|
||||
wsgi_req->sendfile_fd = fd;
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0);
|
||||
wsgi_req->sendfile_fd = -1;
|
||||
return UWSGI_OK;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ret == 0) {
|
||||
if (!wsgi_req->async_placeholder) {
|
||||
wsgi_req->async_placeholder = PyObject_GetIter((PyObject *) wsgi_req->async_result);
|
||||
if (!wsgi_req->async_placeholder)
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
PyObject *pychunk = PyIter_Next((PyObject *) wsgi_req->async_placeholder);
|
||||
if (!pychunk)
|
||||
return UWSGI_OK;
|
||||
ret = uwsgi_python_send_body(wsgi_req, pychunk);
|
||||
if (ret == 0) {
|
||||
if (PyInt_Check(pychunk) || PyObject_HasAttrString(pychunk, "fileno")) {
|
||||
// is it a file ?
|
||||
int fd = PyObject_AsFileDescriptor(pychunk);
|
||||
if (fd >= 0) {
|
||||
wsgi_req->sendfile_fd = fd;
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0);
|
||||
wsgi_req->sendfile_fd = -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
Py_DECREF(pychunk);
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
int uwsgi_request_python_raw(struct wsgi_request *wsgi_req) {
|
||||
if (!up.raw_callable)
|
||||
return UWSGI_OK;
|
||||
|
||||
// back from async
|
||||
if (wsgi_req->async_force_again) {
|
||||
UWSGI_GET_GIL int ret = manage_raw_response(wsgi_req);
|
||||
if (ret == UWSGI_AGAIN) {
|
||||
wsgi_req->async_force_again = 1;
|
||||
UWSGI_RELEASE_GIL return UWSGI_AGAIN;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
|
||||
UWSGI_GET_GIL PyObject * args = PyTuple_New(1);
|
||||
PyTuple_SetItem(args, 0, PyInt_FromLong(wsgi_req->fd));
|
||||
wsgi_req->async_result = PyEval_CallObject(up.raw_callable, args);
|
||||
Py_DECREF(args);
|
||||
if (wsgi_req->async_result) {
|
||||
for (;;) {
|
||||
int ret = manage_raw_response(wsgi_req);
|
||||
if (ret == UWSGI_AGAIN) {
|
||||
wsgi_req->async_force_again = 1;
|
||||
if (uwsgi.async > 1) {
|
||||
UWSGI_RELEASE_GIL return UWSGI_AGAIN;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
end:
|
||||
if (PyErr_Occurred())
|
||||
PyErr_Print();
|
||||
if (wsgi_req->async_result) {
|
||||
Py_DECREF((PyObject *) wsgi_req->async_result);
|
||||
}
|
||||
UWSGI_RELEASE_GIL;
|
||||
return UWSGI_OK;
|
||||
}
|
||||
@@ -265,7 +265,7 @@ PyObject *py_uwsgi_add_file_monitor(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
|
||||
|
||||
char *func;
|
||||
uint16_t size = 0;
|
||||
uint64_t size = 0;
|
||||
PyObject *py_func;
|
||||
int argc = PyTuple_Size(args);
|
||||
int i;
|
||||
@@ -331,7 +331,7 @@ PyObject *py_uwsgi_rpc_list(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
|
||||
|
||||
char *node = NULL, *func;
|
||||
uint16_t size = 0;
|
||||
uint64_t size = 0;
|
||||
PyObject *py_node, *py_func;
|
||||
|
||||
int argc = PyTuple_Size(args);
|
||||
@@ -3169,6 +3169,111 @@ static PyMethodDef uwsgi_queue_methods[] = {
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
PyObject *py_uwsgi_metric_inc(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
int64_t value = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|l:metric_inc", &key, &value)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_metric_inc(key, NULL, value)) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_metric_dec(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
int64_t value = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|l:metric_dec", &key, &value)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_metric_dec(key, NULL, value)) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_metric_mul(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
int64_t value = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|l:metric_mul", &key, &value)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_metric_mul(key, NULL, value)) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_metric_div(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
int64_t value = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|l:metric_div", &key, &value)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_metric_div(key, NULL, value)) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_metric_set(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
int64_t value = 1;
|
||||
if (!PyArg_ParseTuple(args, "s|l:metric_set", &key, &value)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
if (uwsgi_metric_set(key, NULL, value)) {
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
UWSGI_GET_GIL
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_metric_get(PyObject * self, PyObject * args) {
|
||||
char *key;
|
||||
if (!PyArg_ParseTuple(args, "s:metric_get", &key)) return NULL;
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int64_t value = uwsgi_metric_get(key, NULL);
|
||||
UWSGI_GET_GIL
|
||||
return PyLong_FromLongLong(value);
|
||||
}
|
||||
|
||||
|
||||
static PyMethodDef uwsgi_metrics_methods[] = {
|
||||
{"metric_inc", py_uwsgi_metric_inc, METH_VARARGS, ""},
|
||||
{"metric_dec", py_uwsgi_metric_dec, METH_VARARGS, ""},
|
||||
{"metric_mul", py_uwsgi_metric_mul, METH_VARARGS, ""},
|
||||
{"metric_div", py_uwsgi_metric_div, METH_VARARGS, ""},
|
||||
{"metric_get", py_uwsgi_metric_get, METH_VARARGS, ""},
|
||||
{"metric_set", py_uwsgi_metric_set, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
void init_uwsgi_module_spooler(PyObject * current_uwsgi_module) {
|
||||
@@ -3204,6 +3309,12 @@ void init_uwsgi_module_advanced(PyObject * current_uwsgi_module) {
|
||||
Py_DECREF(func);
|
||||
}
|
||||
|
||||
for (uwsgi_function = uwsgi_metrics_methods; uwsgi_function->ml_name != NULL; uwsgi_function++) {
|
||||
PyObject *func = PyCFunction_New(uwsgi_function, NULL);
|
||||
PyDict_SetItemString(uwsgi_module_dict, uwsgi_function->ml_name, func);
|
||||
Py_DECREF(func);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void init_uwsgi_module_cache(PyObject * current_uwsgi_module) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
#include <Python.h>
|
||||
|
||||
#include <frameobject.h>
|
||||
@@ -180,6 +180,11 @@ struct uwsgi_python {
|
||||
int start_response_nodelay;
|
||||
|
||||
char *programname;
|
||||
int wsgi_strict;
|
||||
int wsgi_accept_buffer;
|
||||
|
||||
char *raw;
|
||||
PyObject *raw_callable;
|
||||
};
|
||||
|
||||
|
||||
@@ -276,6 +281,10 @@ struct uwsgi_buffer *uwsgi_python_exception_repr(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_python_backtrace(struct wsgi_request *);
|
||||
void uwsgi_python_exception_log(struct wsgi_request *);
|
||||
|
||||
int uwsgi_python_send_body(struct wsgi_request *, PyObject *);
|
||||
|
||||
int uwsgi_request_python_raw(struct wsgi_request *);
|
||||
|
||||
#define py_current_wsgi_req() current_wsgi_req();\
|
||||
if (!wsgi_req) {\
|
||||
return PyErr_Format(PyExc_SystemError, "you can call uwsgi api function only from the main callable");\
|
||||
|
||||
@@ -11,7 +11,7 @@ def get_python_version():
|
||||
return version
|
||||
|
||||
NAME='python'
|
||||
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter', 'tracebacker']
|
||||
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter', 'tracebacker', 'raw']
|
||||
|
||||
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
|
||||
LDFLAGS = []
|
||||
@@ -32,9 +32,17 @@ if not 'UWSGI_PYTHON_NOLIB' in os.environ:
|
||||
# try 3.x style config dir
|
||||
if not os.path.exists(libdir):
|
||||
libdir = '%s/lib/python%s/config-%s' % (sys.prefix, version, get_python_version())
|
||||
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LDLIBRARY'))
|
||||
if not os.path.exists(libpath):
|
||||
|
||||
# get cpu type
|
||||
uname = os.uname()
|
||||
if uname[4].startswith('arm'):
|
||||
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LIBRARY'))
|
||||
if not os.path.exists(libpath):
|
||||
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LDLIBRARY'))
|
||||
else:
|
||||
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LDLIBRARY'))
|
||||
if not os.path.exists(libpath):
|
||||
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LIBRARY'))
|
||||
if not os.path.exists(libpath):
|
||||
libpath = '%s/libpython%s.a' % (libdir, version)
|
||||
LIBS.append(libpath)
|
||||
|
||||
@@ -292,6 +292,8 @@ PyObject *py_eventfd_write(PyObject * self, PyObject * args) {
|
||||
|
||||
int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (wsgi_req->is_raw) return uwsgi_request_python_raw(wsgi_req);
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
if (wsgi_req->async_force_again) {
|
||||
|
||||
@@ -5,6 +5,78 @@ extern struct uwsgi_python up;
|
||||
extern struct uwsgi_plugin python_plugin;
|
||||
extern PyTypeObject uwsgi_InputType;
|
||||
|
||||
/*
|
||||
|
||||
Albeit PEP 333/3333 is clear about what kind of return object we must
|
||||
expect from a WSGI callable, we CAN use the buffer api to optimize for lower-level
|
||||
returns type: bytes, bytearray, array.array
|
||||
|
||||
to enable this optimization add --wsgi-accept-buffer
|
||||
|
||||
NOTE: this is a violation of the standards !!! use only if you know the implications !!!
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_python_send_body(struct wsgi_request *wsgi_req, PyObject *chunk) {
|
||||
char *content = NULL;
|
||||
size_t content_len = 0;
|
||||
|
||||
if (!up.wsgi_accept_buffer && !wsgi_req->is_raw) goto strict;
|
||||
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
|
||||
Py_buffer pbuf;
|
||||
int has_buffer = 0;
|
||||
#endif
|
||||
|
||||
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
|
||||
if (PyObject_CheckBuffer(chunk)) {
|
||||
if (!PyObject_GetBuffer(chunk, &pbuf, PyBUF_SIMPLE)) {
|
||||
content = (char *) pbuf.buf;
|
||||
content_len = (size_t) pbuf.len;
|
||||
has_buffer = 1;
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (PyObject_CheckReadBuffer(chunk)) {
|
||||
#ifdef UWSGI_PYTHON_OLD
|
||||
int buffer_len = 0;
|
||||
if (!PyObject_AsCharBuffer(chunk, (const char **) &content, &buffer_len)) {
|
||||
#else
|
||||
if (!PyObject_AsCharBuffer(chunk, (const char **) &content, (Py_ssize_t *) &content_len)) {
|
||||
#endif
|
||||
PyErr_Clear();
|
||||
goto found;
|
||||
}
|
||||
#ifdef UWSGI_PYTHON_OLD
|
||||
content_len = buffer_len;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
strict:
|
||||
// fallback
|
||||
if (PyString_Check(chunk)) {
|
||||
content = PyString_AsString(chunk);
|
||||
content_len = PyString_Size(chunk);
|
||||
}
|
||||
|
||||
found:
|
||||
if (content) {
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_response_write_body_do(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
#if defined(PYTHREE) || defined(Py_TPFLAGS_HAVE_NEWBUFFER)
|
||||
if (has_buffer) PyBuffer_Release(&pbuf);
|
||||
#endif
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
this is a hack for supporting non-file object passed to wsgi.file_wrapper
|
||||
*/
|
||||
@@ -169,19 +241,11 @@ int uwsgi_response_subhandler_wsgi(struct wsgi_request *wsgi_req) {
|
||||
PyObject *pychunk;
|
||||
|
||||
// return or yield ?
|
||||
if (PyString_Check((PyObject *)wsgi_req->async_result)) {
|
||||
char *content = PyString_AsString((PyObject *)wsgi_req->async_result);
|
||||
size_t content_len = PyString_Size((PyObject *)wsgi_req->async_result);
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_response_write_body_do(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
}
|
||||
goto clear;
|
||||
// in strict mode we do not optimize apps directly returning strings (or bytes)
|
||||
if (!up.wsgi_strict) {
|
||||
if (uwsgi_python_send_body(wsgi_req, (PyObject *)wsgi_req->async_result)) goto clear;
|
||||
}
|
||||
|
||||
|
||||
if (wsgi_req->sendfile_obj == wsgi_req->async_result) {
|
||||
if (wsgi_req->sendfile_fd >= 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
@@ -222,19 +286,13 @@ exception:
|
||||
|
||||
|
||||
|
||||
if (PyString_Check(pychunk)) {
|
||||
char *content = PyString_AsString(pychunk);
|
||||
size_t content_len = PyString_Size(pychunk);
|
||||
UWSGI_RELEASE_GIL
|
||||
uwsgi_response_write_body_do(wsgi_req, content, content_len);
|
||||
UWSGI_GET_GIL
|
||||
uwsgi_py_check_write_errors {
|
||||
uwsgi_py_write_exception(wsgi_req);
|
||||
int ret = uwsgi_python_send_body(wsgi_req, pychunk);
|
||||
if (ret != 0) {
|
||||
if (ret < 0) {
|
||||
Py_DECREF(pychunk);
|
||||
goto clear;
|
||||
}
|
||||
}
|
||||
|
||||
else if (wsgi_req->sendfile_obj == pychunk) {
|
||||
if (wsgi_req->sendfile_fd >= 0) {
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
+97
-1
@@ -7,6 +7,88 @@ extern struct uwsgi_plugin rack_plugin;
|
||||
|
||||
#define uwsgi_rack_api(x, y, z) rb_define_module_function(rb_uwsgi_embedded, x, y, z)
|
||||
|
||||
static VALUE rack_uwsgi_metric_get(VALUE *class, VALUE key) {
|
||||
Check_Type(key, T_STRING);
|
||||
int64_t value = uwsgi_metric_get(RSTRING_PTR(key), NULL);
|
||||
return LONG2NUM(value);
|
||||
}
|
||||
|
||||
static VALUE rack_uwsgi_metric_set(VALUE *class, VALUE key, VALUE val) {
|
||||
Check_Type(key, T_STRING);
|
||||
Check_Type(val, T_FIXNUM); // should be T_BIGNUM...
|
||||
if (uwsgi_metric_set(RSTRING_PTR(key), NULL, NUM2LONG(val) )) {
|
||||
return Qnil;
|
||||
}
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
static VALUE rack_uwsgi_metric_inc(int argc, VALUE *argv, VALUE *class) {
|
||||
int64_t value = 1;
|
||||
if (argc == 0) return Qnil;
|
||||
Check_Type(argv[0], T_STRING);
|
||||
|
||||
if (argc > 1) {
|
||||
Check_Type(argv[1], T_FIXNUM); // should be T_BIGNUM...
|
||||
value = NUM2LONG(argv[1]);
|
||||
}
|
||||
|
||||
if (uwsgi_metric_inc(RSTRING_PTR(argv[0]), NULL, value )) {
|
||||
return Qnil;
|
||||
}
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
static VALUE rack_uwsgi_metric_dec(int argc, VALUE *argv, VALUE *class) {
|
||||
int64_t value = 1;
|
||||
if (argc == 0) return Qnil;
|
||||
Check_Type(argv[0], T_STRING);
|
||||
|
||||
if (argc > 1) {
|
||||
Check_Type(argv[1], T_FIXNUM); // should be T_BIGNUM...
|
||||
value = NUM2LONG(argv[1]);
|
||||
}
|
||||
|
||||
if (uwsgi_metric_dec(RSTRING_PTR(argv[0]), NULL, value )) {
|
||||
return Qnil;
|
||||
}
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
static VALUE rack_uwsgi_metric_mul(int argc, VALUE *argv, VALUE *class) {
|
||||
int64_t value = 1;
|
||||
if (argc == 0) return Qnil;
|
||||
Check_Type(argv[0], T_STRING);
|
||||
|
||||
if (argc > 1) {
|
||||
Check_Type(argv[1], T_FIXNUM); // should be T_BIGNUM...
|
||||
value = NUM2LONG(argv[1]);
|
||||
}
|
||||
|
||||
if (uwsgi_metric_mul(RSTRING_PTR(argv[0]), NULL, value )) {
|
||||
return Qnil;
|
||||
}
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
static VALUE rack_uwsgi_metric_div(int argc, VALUE *argv, VALUE *class) {
|
||||
int64_t value = 1;
|
||||
if (argc == 0) return Qnil;
|
||||
Check_Type(argv[0], T_STRING);
|
||||
|
||||
if (argc > 1) {
|
||||
Check_Type(argv[1], T_FIXNUM); // should be T_BIGNUM...
|
||||
value = NUM2LONG(argv[1]);
|
||||
}
|
||||
|
||||
if (uwsgi_metric_div(RSTRING_PTR(argv[0]), NULL, value )) {
|
||||
return Qnil;
|
||||
}
|
||||
return Qtrue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
|
||||
|
||||
Check_Type(rbmessage, T_STRING);
|
||||
@@ -59,6 +141,11 @@ static VALUE rack_uwsgi_i_am_the_lord(VALUE *class, VALUE legion_name) {
|
||||
}
|
||||
#endif
|
||||
|
||||
static VALUE rack_uwsgi_connection_fd(VALUE *class) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
return INT2NUM(wsgi_req->fd);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
|
||||
@@ -718,7 +805,7 @@ static VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
|
||||
static VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
|
||||
|
||||
char *node = NULL, *func;
|
||||
uint16_t size = 0;
|
||||
uint64_t size = 0;
|
||||
|
||||
char *argv[256];
|
||||
uint16_t argvs[256];
|
||||
@@ -1084,6 +1171,8 @@ void uwsgi_rack_init_api() {
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_rack_api("i_am_the_lord", rack_uwsgi_i_am_the_lord, 1);
|
||||
#endif
|
||||
|
||||
uwsgi_rack_api("connection_fd", rack_uwsgi_connection_fd, 0);
|
||||
|
||||
|
||||
uwsgi_rack_api("cache_get", rack_uwsgi_cache_get, -1);
|
||||
@@ -1099,6 +1188,13 @@ void uwsgi_rack_init_api() {
|
||||
uwsgi_rack_api("cache_clear", rack_uwsgi_cache_clear, -1);
|
||||
uwsgi_rack_api("cache_clear!", rack_uwsgi_cache_clear_exc, -1);
|
||||
|
||||
uwsgi_rack_api("metric_get", rack_uwsgi_metric_get, 1);
|
||||
uwsgi_rack_api("metric_set", rack_uwsgi_metric_set, 2);
|
||||
uwsgi_rack_api("metric_inc", rack_uwsgi_metric_inc, -1);
|
||||
uwsgi_rack_api("metric_dec", rack_uwsgi_metric_dec, -1);
|
||||
uwsgi_rack_api("metric_mul", rack_uwsgi_metric_mul, -1);
|
||||
uwsgi_rack_api("metric_div", rack_uwsgi_metric_div, -1);
|
||||
|
||||
VALUE uwsgi_rb_opt_hash = rb_hash_new();
|
||||
int i;
|
||||
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
|
||||
|
||||
+16
-19
@@ -315,7 +315,7 @@ VALUE rack_call_rpc_handler(VALUE args) {
|
||||
}
|
||||
|
||||
|
||||
uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
|
||||
uint64_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char **buffer) {
|
||||
|
||||
uint8_t i;
|
||||
VALUE rb_args = rb_ary_new2(2);
|
||||
@@ -343,8 +343,9 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[],
|
||||
if (TYPE(ret) == T_STRING) {
|
||||
rv = RSTRING_PTR(ret);
|
||||
rl = RSTRING_LEN(ret);
|
||||
if (rl <= 0xffff) {
|
||||
memcpy(buffer, rv, rl);
|
||||
if (rl > 0) {
|
||||
*buffer = uwsgi_malloc(rl);
|
||||
memcpy(*buffer, rv, rl);
|
||||
return rl;
|
||||
}
|
||||
}
|
||||
@@ -416,6 +417,18 @@ void uwsgi_ruby_gem_set_apply(char *gemset) {
|
||||
|
||||
void uwsgi_ruby_gemset(char *gemset) {
|
||||
|
||||
struct uwsgi_string_list *rvm_paths = ur.rvm_path;
|
||||
while(rvm_paths) {
|
||||
char *filename = uwsgi_concat3(rvm_paths->value, "/environments/", gemset);
|
||||
if (uwsgi_file_exists(filename)) {
|
||||
uwsgi_ruby_gem_set_apply(filename);
|
||||
free(filename);
|
||||
return;
|
||||
}
|
||||
free(filename);
|
||||
rvm_paths = rvm_paths->next;
|
||||
}
|
||||
|
||||
char *home = getenv("HOME");
|
||||
|
||||
if (home) {
|
||||
@@ -436,18 +449,6 @@ void uwsgi_ruby_gemset(char *gemset) {
|
||||
}
|
||||
free(filename);
|
||||
|
||||
struct uwsgi_string_list *rvm_paths = ur.rvm_path;
|
||||
while(rvm_paths) {
|
||||
char *filename = uwsgi_concat3(rvm_paths->value, "/environments/", gemset);
|
||||
if (uwsgi_file_exists(filename)) {
|
||||
uwsgi_ruby_gem_set_apply(filename);
|
||||
free(filename);
|
||||
return;
|
||||
}
|
||||
free(filename);
|
||||
rvm_paths = rvm_paths->next;
|
||||
}
|
||||
|
||||
uwsgi_log("ERROR: unable to load gemset %s !!!\n", gemset);
|
||||
exit(1);
|
||||
|
||||
@@ -1106,7 +1107,6 @@ static void uwsgi_rack_hijack(void) {
|
||||
uwsgi_error("dup2()");
|
||||
}
|
||||
}
|
||||
int ret = -1;
|
||||
int error = 0;
|
||||
if (ur.rbshell[0] != 0) {
|
||||
rb_eval_string(ur.rbshell);
|
||||
@@ -1122,9 +1122,6 @@ static void uwsgi_rack_hijack(void) {
|
||||
exit(UWSGI_DE_HIJACKED_CODE);
|
||||
}
|
||||
|
||||
if (ret == 0) {
|
||||
exit(UWSGI_QUIET_CODE);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user