Compare commits

..
120 Commits
Author SHA1 Message Date
Unbit 6adbc37a31 removed old-style changelog 2013-08-23 14:57:06 +02:00
Unbit 688d3fff8c fixed python3 static files handling 2013-08-23 14:51:18 +02:00
Unbit c0b079deb0 backported python3 latin1 fix from 1.9 2013-07-02 16:22:20 +02:00
Unbit 9b30c8683b fixed backtrace-depth 2013-05-23 19:40:21 +02:00
Unbit 9113812b0d fixed python3 pyargv 2013-05-19 05:04:42 +02:00
Unbit 1abe9f2d12 fixed mule_msg 2013-05-18 18:27:11 +02:00
Unbit 9a37b3653f uWSGI 1.4.9 2013-03-09 10:01:34 +01:00
Unbit 65ad341a31 backported cache_update for lua and fixed its lock handling 2013-03-07 13:28:50 +01:00
Unbit bd31548903 re-try semop() on interrupt 2013-03-07 13:17:46 +01:00
Unbit dd536cf7ea removed jvm and jwsgi plugin as in 1.9 we have a really working implementation 2013-03-06 20:08:29 +01:00
Unbit efa27dfc6c better broodlord num computation 2013-03-06 19:56:55 +01:00
Unbit 91b14e0b34 improved broodlord mode 2013-03-06 19:13:32 +01:00
Unbit 74b3d25bcf call ERR_clear_error after each https session close 2013-03-06 10:36:05 +01:00
Unbit 3857e26e4c avoid crashing carbon on master shutdown 2013-03-03 13:43:55 +01:00
Unbit c7d3a27225 backported http-socket-modifier1/2 2013-03-02 16:25:17 +01:00
Unbit 4f50b4aafc completetd gemspec 2013-03-02 14:58:58 +01:00
Unbit d172fb4909 fixed gem generation 2013-03-02 14:49:03 +01:00
Unbit c842bb4917 allows building uwsgi as a gem 2013-03-02 14:37:14 +01:00
Unbit d6da6848be manage https re-handshake and fix gevent timeout management 2013-03-02 09:54:10 +01:00
Unbit b1caf56f49 various minor fixes in gateway initialization 2013-03-02 08:35:56 +01:00
Unbit 00c243bcce backported --for-glob 2013-03-01 15:23:38 +01:00
Unbit 575dd6beee backported add_timer and add_rb_timer for perl/psgi plugin 2013-03-01 15:20:40 +01:00
unbit 645d021d73 Merge pull request #166 from prymitive/carbon_hostname14
backported carbon hostname patch to 1.4.x
2013-03-01 06:18:52 -08:00
Łukasz Mierzwa 0ca320e5fd backported carbon hostname patch to 1.4.x 2013-03-01 15:15:46 +01:00
Unbit 7879a010e8 backported negative --log-alarm 2013-02-27 04:39:55 +01:00
Unbit 43dd1029ad fixed usage of ipcsem on linux 2013-02-27 04:26:59 +01:00
Unbit ce7d84b865 try to avoid the need to sync cache_first_available_item with cache_unused_stack 2013-02-27 01:43:03 +01:00
Unbit 7ab1795075 let's prepare for 1.4.7 2013-02-27 01:27:49 +01:00
Unbit e1ce4e1011 backporetd new carbon plugin and stats pusher subsystem 2013-02-27 01:26:24 +01:00
Unbit 0c02a5104a removed the old/broken/useless mono plugin, a new one will be in 1.9 2013-02-25 08:39:43 +01:00
Unbit 0e244fc59c added support for ruby 2 2013-02-25 07:34:34 +01:00
Unbit 5d6086c84a allows --attach-daemon without workers 2013-02-23 14:46:41 +01:00
Unbit a45be4f7a9 backported perl async fixes from 1.9 2013-02-23 13:35:41 +01:00
Unbit dd63bef92e backported --perl-arg and --perl-args 2013-02-23 13:28:51 +01:00
Unbit 621a05d879 another heroku python fix 2013-02-23 13:26:05 +01:00
Unbit b857690caf backported python plugin new build system (heroku friendly) 2013-02-23 12:07:45 +01:00
Unbit edb0a72dfd fixed a refcnt bug in psgi plugin 2013-02-23 08:26:08 +01:00
Unbit da4af442ad prepare for uWSGI 1.4.6 2013-02-20 16:03:27 +01:00
Unbit 04ff580075 improved muleloop in uwsgidecoraotors 2013-02-19 07:12:44 +01:00
Unbit 5925db13cf backported more logvars 2013-02-18 13:09:53 +01:00
Unbit d283fd1aae fixed master + emperor 2013-02-12 16:44:14 +01:00
Unbit 345b22d8f0 forget to reset SIGCHLD to SIG_DFL 2013-02-10 20:12:47 +01:00
Unbit b8fc89166d reset sigmask on startup 2013-02-10 19:52:50 +01:00
Unbit 50ffb9d258 reapply fixed-SERVER_PORT-in-routers-when-shared-sockets-are.patch 2013-02-09 17:34:31 +01:00
Unbit 9ae1b26d52 fixed suspend when harakiri is in place 2013-02-07 14:11:24 +01:00
Unbit f281d21a1b backported improved alarm_xmpp plugin 2013-01-31 09:59:54 +01:00
Unbit b9a2b92005 fixed PTHREAD_MUTEX_ROBUST [4] 2013-01-30 18:28:23 +01:00
Unbit 92a26d4ff6 fixed PTHREAD_MUTEX_ROBUST [3] 2013-01-30 18:26:24 +01:00
Unbit 51360416a7 fixed PTHREAD_MUTEX_ROBUST [2] 2013-01-30 18:20:22 +01:00
Unbit c7bc98a50c fixed PTHREAD_MUTEX_ROBUST 2013-01-30 18:16:24 +01:00
Unbit b4b5c0175a added __USE_UNIX98 to pthread.h 2013-01-30 18:14:37 +01:00
Unbit 7ed3eb36ee fixed PTHREAD_PRIO_INHERIT 2013-01-30 18:09:48 +01:00
Unbit 05c475f597 added --thunder-lock 2013-01-30 18:02:03 +01:00
Unbit c750dfc1e3 Revert "fixed SERVER_PORT in routers when shared sockets are in place"
This reverts commit 01b14f4395.
2013-01-30 16:57:59 +01:00
Unbit 01b14f4395 fixed SERVER_PORT in routers when shared sockets are in place 2013-01-30 16:32:19 +01:00
Unbit 46d7d4bf1d completed new logvars backport 2013-01-28 23:03:17 +01:00
Unbit 02d76f12e0 backported new logvars from 1.5 2013-01-28 22:44:54 +01:00
Unbit 719860a349 backported new rbtree implementation 2013-01-28 22:34:25 +01:00
Unbit 5cce0935fd backported master+emperor fix from 1.5 2013-01-28 16:37:13 +01:00
Unbit 24ef2a838f backported --touch-reload refactoring from 1.5 2013-01-28 16:23:57 +01:00
Unbit 8aa739b4b2 backported --emperor-procname 2013-01-26 04:20:00 +01:00
Unbit 9221e1953e fixed a cache collision bug 2013-01-23 20:22:28 +01:00
Roberto De Ioris 18592fb2bd fixed async mode when multiple fds are in place 2013-01-22 18:31:37 +01:00
Roberto De Ioris fc80eeb581 fixed bug in python uwsgi.workers() 2013-01-21 14:53:01 +01:00
Roberto De Ioris bc19b58681 prepare for uWSGI 1.4.5 2013-01-21 12:13:56 +01:00
Roberto De Ioris 8f2202eab5 reset cores/requests on worker startup 2013-01-21 12:13:32 +01:00
Roberto De Ioris aa2ecf14df correctly handle multithread exit 2013-01-21 12:09:25 +01:00
Roberto De Ioris 43f5792826 fixed test.psgi 2013-01-20 17:08:25 +01:00
unbit 36ff37e12c Update core/uwsgi.c 2013-01-18 09:21:16 +01:00
Roberto De Ioris 6dd6f961e8 removed a useless log 2013-01-16 19:34:41 +01:00
Roberto De Ioris 5dd5d92ffb fixed mule management 2013-01-16 17:10:22 +01:00
Roberto De Ioris 64f1b844bd fixed unix signal usage in mules and spooler 2013-01-16 16:50:10 +01:00
Roberto De Ioris e562c4691d fixed http-socket body storage leak 2013-01-16 16:27:47 +01:00
Roberto De Ioris 1cbab74f0e backported uwsgi::postfork and uwsgi::atexit 2013-01-16 14:52:13 +01:00
Roberto De Ioris 3053fdb25a backported --php-fallback 2013-01-14 16:44:30 +01:00
Roberto De Ioris f11f542242 improved mod_proxy_uwsgi 2013-01-13 12:37:22 +01:00
Roberto De Ioris 32ddf10cfa applied feature-extract-dump-the-specified-address-to-stdout.patch 2013-01-13 05:39:43 +01:00
Roberto De Ioris 1b54be396c applied Lua-bindings-for-lock-unlock-functions.patch 2013-01-13 05:38:01 +01:00
Roberto De Ioris f81a4f9736 fixed gevent leak 2013-01-12 17:18:53 +01:00
Roberto De Ioris 048b339593 allows building on debian etch 4 2013-01-10 22:26:24 +01:00
Roberto De Ioris 081a6b90bf added --python-version and --perl-version 2013-01-05 08:39:18 +01:00
Roberto De Ioris 97f1b6d649 fixed broodlord mode stats 2013-01-04 20:42:53 +01:00
Roberto De Ioris 593aba2b19 improved mod_proxy_uwsgi 2012-12-30 11:05:20 +01:00
Roberto De Ioris 47c9e5e3f0 fixed /proc check 2012-12-30 09:10:10 +01:00
Roberto De Ioris bca8bc0c4d fixed socket naming of fd 0 2012-12-30 09:07:38 +01:00
Roberto De Ioris a67dfdd542 fixed a https/corerouter corner-case bug 2012-12-21 11:32:33 +01:00
Roberto De Ioris d1bbe7e3f9 set HTTPS to on when behind stud 2012-12-21 09:01:10 +01:00
Roberto De Ioris 442c982aff backported --http-stud-prefix 2012-12-19 18:41:48 +01:00
Roberto De Ioris a2f50ccf2e report pos in failed uploads 2012-12-16 12:58:12 +01:00
Roberto De Ioris b1c5fef0dc fixed computation of post data 2012-12-16 12:18:13 +01:00
Roberto De Ioris f6d8ac52f4 applied more debug to https 2012-12-16 10:59:56 +01:00
Roberto De Ioris 94e4fcbfe1 added additional uwgsi-gevent error report 2012-12-15 20:36:26 +01:00
Roberto De Ioris c9e7b0f48e fixed wrong typecasting in yaml and fixed subscription system on 32 bit 2012-12-15 14:32:25 +01:00
Roberto De Ioris 2f932d8ca0 backported http internal router fixes 2012-12-13 15:34:47 +01:00
Roberto De Ioris c517320f7a prepare for next release (1.4.4) 2012-12-13 11:07:55 +01:00
Roberto De Ioris b0dae66264 applied 0001-allows-embedding-.cc-and-.m-files.patch 2012-12-13 11:07:37 +01:00
Roberto De Ioris 0d87ed7298 fix dup2() usage 2012-12-12 15:23:04 +01:00
Roberto De Ioris fd3291b11f uWSGI 1.4.3 2012-12-10 15:26:09 +01:00
Roberto De Ioris e5ac5d6352 added emperor:// to supported scheme 2012-12-10 14:16:13 +01:00
Roberto De Ioris 403bd604e2 backported fix for bug #66 2012-12-10 14:14:01 +01:00
Roberto De Ioris 045d8947ae applied 0001-missing-new-line-in-carbon-plugin-logs.patch 2012-12-10 14:12:29 +01:00
Roberto De Ioris a9f2c71863 applied 0001-fallback-to-REMOTE_ADDR-if-HTTP_X_FORWARDED_FOR-is-m.patch 2012-12-10 14:11:42 +01:00
Roberto De Ioris b504a1ebe8 applied 0001-fixed-log-format-in-cheaper_busyness.patch 2012-12-10 14:10:28 +01:00
Roberto De Ioris f05ce0d2fc applied 0001-improved-stdin-management-in-cron.patch 2012-12-10 14:08:55 +01:00
Roberto De Ioris a2f3c716b1 applied 0001-added-offload-thread-alias.patch 2012-12-10 14:06:39 +01:00
Roberto De Ioris 2d7ca36f60 preparing for 1.4.3 2012-12-10 14:05:30 +01:00
unbit 5370e535dd core: make smart-attach-daemon smart enough
Avoid call storming of pidfile check that leads to multiple daemons
running instead of one. Fix #65.
2012-11-28 20:52:59 +01:00
unbit 092767c29f Merge pull request #63 from xrmx/cpucount14
uwsgiconfig: permit to override CPUCOUNT with environment variable
2012-11-27 10:32:45 -08:00
Riccardo Magliocchetti 4e119e6838 uwsgiconfig: permit to override CPUCOUNT with environment variable
CPUCOUNT=X make

will force X cores instead of the autodetected ones
2012-11-27 19:25:49 +01:00
Roberto De Ioris 87ef444ea6 uWSGI 1.4.2 2012-11-24 11:27:06 +01:00
Roberto De Ioris 714be76f9b improved QUERY_STRING handling in router_rewrite, added --php-var 2012-11-24 11:26:25 +01:00
Roberto De Ioris af0f0da8c2 added --php-app-qs 2012-11-24 10:11:56 +01:00
Roberto De Ioris 8407372801 fixed PATH_TRANSLATED in php and improved offloading of bigger files 2012-11-24 10:11:12 +01:00
Roberto De Ioris d19c4e84fc applied 0001-fixed-corner-case-ssl-body-reading.patch 2012-11-24 10:10:08 +01:00
Roberto De Ioris 3342852a9a backported 0001-do-not-crash-on-non-existent-config-files.patch 2012-11-21 07:49:13 +01:00
Roberto De Ioris 586a02d849 backported fixes from 1.5 2012-11-21 07:42:32 +01:00
Roberto De Ioris 188dad744a uWSGI 1.4.1 2012-11-13 04:53:32 +01:00
Roberto De Ioris 6cf3bbea69 backported fixed for offloading, static maps and non-blocking connect 2012-11-13 04:41:14 +01:00
Roberto De Ioris 04736d371e backported 0001-corerouter-NOT-courerouter.patch 2012-11-12 13:33:14 +01:00
Roberto De Ioris cc9151f89e 'wsgi' option is an alias for 'module' not 'wsgi-file' 2012-11-12 11:57:55 +01:00
461 changed files with 22665 additions and 53684 deletions
-8
View File
@@ -1,13 +1,5 @@
*.o
*.py[co]
*.class
*.jar
*~
*.so
/uwsgi
/uwsgibuild.*
/t/ring/target
core/dot_h.c
+4
View File
@@ -0,0 +1,4 @@
syntax: glob
*.o
*.pyc
+58
View File
@@ -0,0 +1,58 @@
d3850b52334a91d005b0fe45e1e38ba0997a1fb8 no_server mode
2d8a617299153ed2efa6ecee7920e9d36c29e0f5 0.9.5beta1
04722a2d0121080d14a64df097c278860db5ce8a 0.9.5rc1
820cc64ab296dc4589ef72a33a6b804c22a0430c 0.9.5rc2
b0db39cfad5ac6d4f00bbb3f9c57cf73206e2afb 0.9.5
9f8b98ad1dfa51b86b13fa624c65f73523075fc4 0.9.5.1
a83e7a482e65befcfbb0e24af8cd5d15190acdd7 0.9.6-rc1
b8f67c6cd0d62f864db9b2b265b4e260ad7d873c 0.9.6-rc2
35918dd4b3771158b2b57410613ef029e08bbd60 0.9.6
5f25d1f97f9dde3e391a668c1c610a52a5db8244 0.9.6.1
ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
9e100c1f085034396cec586f0c76ad3f9800d1a5 0.9.7-beta1
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
42efe1f329005618c8b44f901979ebcecd5216fb 0.9.8
fd8477b6348faf16588106055ca59df1c488f76a 0.9.8.1
7169ef1d68d3dab4737bcc3f9e082839e5a06cc1 0.9.8.2
f4d3c4dcd7a63e21fcc9d8d567374c69935178bd 0.9.8.3
6945ee03c7ea95eb19217ef1e1fb17d9ae26adbc 0.9.9-beta1
fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
6aa667612019fcff8e68af9469f73aff6fa378a8 0.9.9-rc2
376ffd8f190623e5e2521fe9fa64bf03c31e71be 0.9.9
7048ae11cfc8453c6bb599af3c0dfacd7ebae43c 1.0-rc1
7a4e021ea7ba2953e474326612c3bb82d6817f0e 1.0-rc2
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
3c70927335856883283fe4db448e092cecc0ccdb 1.0
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
901f0cb5de36ea907b26d64ac9ce54605ec531d2 1.1-rc2
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
c3cdecbf2bac591336baddd14f9ac22e18d6e200 1.2
14524da00a8b382dffb1d16a0e70cdf4a946f369 1.3-rc2
883b946db9038372cb1d76cb1d328a3093140e7b 1.3-rc3
aeea5a5d2e8b62ad55e23d539e1be02f2b6962af 1.3-rc4
620e0cb6ccdb0ce27561b4240cb3a0ef4c3527fd 1.3
-44
View File
@@ -1,44 +0,0 @@
language: c
compiler:
- gcc
- clang
script:
- echo -e "\n\n>>> Building uWSGI binary"
- /usr/bin/python uwsgiconfig.py --build travis
- echo -e "\n\n>>> Building python26 plugin"
- /usr/bin/python2.6 -V
- /usr/bin/python2.6 uwsgiconfig.py --plugin plugins/python base python26
- echo -e "\n\n>>> Building python27 plugin"
- /usr/bin/python2.7 -V
- /usr/bin/python2.7 uwsgiconfig.py --plugin plugins/python base python27
- echo -e "\n\n>>> Building python31 plugin"
- /usr/bin/python3.1 -V
- /usr/bin/python3.1 uwsgiconfig.py --plugin plugins/python base python31
- echo -e "\n\n>>> Building python32 plugin"
- /usr/bin/python3.2 -V
- /usr/bin/python3.2 uwsgiconfig.py --plugin plugins/python base python32
- echo -e "\n\n>>> Building python33 plugin"
- /usr/bin/python3.3 -V
- /usr/bin/python3.3 uwsgiconfig.py --plugin plugins/python base python33
- echo -e "\n\n>>> Building rack 1.8.7 plugin"
- /usr/bin/ruby1.8 -v
- UWSGICONFIG_RUBYPATH=/usr/bin/ruby1.8 /usr/bin/python uwsgiconfig.py --plugin plugins/rack base rack187
- echo -e "\n\n>>> Building rack 1.9.1 plugin"
- /usr/bin/ruby1.9.1 -v
- UWSGICONFIG_RUBYPATH=/usr/bin/ruby1.9.1 /usr/bin/python uwsgiconfig.py --plugin plugins/rack base rack191
- echo -e "\n\n>>> Building cgi plugin"
- /usr/bin/python uwsgiconfig.py --plugin plugins/cgi base
- echo -e "\n\n>>> Building dummy plugin"
- /usr/bin/python uwsgiconfig.py --plugin plugins/dummy base
- echo -e "\n\n>>> Building done, starting tests"
- ./tests/travis.sh
before_install:
- sudo add-apt-repository -y ppa:fkrull/deadsnakes
- sudo apt-get update -qq
- sudo apt-get install -qqyf python2.6-dev python2.7-dev python3.1-dev python3.2-dev python3.3-dev rubygems1.8 ruby1.8-dev ruby1.9.1-dev
- sudo apt-get install -qqyf libxml2-dev libpcre3-dev libcap2-dev
- sudo apt-get install -qqyf curl
-4
View File
@@ -21,7 +21,3 @@ Roy Marples
Aarni Koskela
C Anthony Risinger
Stephen Pierce
Mingli Yuan
Natanael Copa
Roberto Leandrini
Ryan Petrello
-16
View File
@@ -1,19 +1,3 @@
----------------------------------------------------------------------
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 -1
View File
@@ -1,3 +1,3 @@
surprise i am empty !
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
Look in the online documentation on http://projects.unbit.it/uwsgi/
+37 -77
View File
@@ -1,36 +1,6 @@
/*
*** mod_proxy_uwsgi ***
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
To build:
apxs2 -i -c mod_proxy_uwsgi.c
To use:
LoadModule proxy_uwsgi_module /usr/lib/apache2/modules/mod_proxy_uwsgi.so
ProxyPass / uwsgi://127.0.0.1:3031/
Docs:
http://uwsgi-docs.readthedocs.org/en/latest/Apache.html#mod-proxy-uwsgi
apxs2 -i -c mod_proxy_uwsgi.c
*/
#define APR_WANT_MEMFUNC
@@ -217,44 +187,27 @@ static int uwsgi_send_body(request_rec *r, proxy_conn_rec *conn)
return OK;
}
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
static request_rec *ap_proxy_make_fake_req(conn_rec *c, request_rec *r)
static
apr_status_t ap_proxygetline(apr_bucket_brigade *bb, char *s, int n, request_rec *r,
int fold, int *writen)
{
apr_pool_t *pool;
request_rec *rp;
char *tmp_s = s;
apr_status_t rv;
apr_size_t len;
apr_pool_create(&pool, c->pool);
rv = ap_rgetline(&tmp_s, n, &len, r, fold, bb);
apr_brigade_cleanup(bb);
rp = apr_pcalloc(pool, sizeof(*r));
if (rv == APR_SUCCESS) {
*writen = (int) len;
} else if (rv == APR_ENOSPC) {
*writen = n;
} else {
*writen = -1;
}
rp->pool = pool;
rp->status = HTTP_OK;
rp->headers_in = apr_table_make(pool, 50);
rp->subprocess_env = apr_table_make(pool, 50);
rp->headers_out = apr_table_make(pool, 12);
rp->err_headers_out = apr_table_make(pool, 5);
rp->notes = apr_table_make(pool, 5);
rp->server = r->server;
rp->log = r->log;
rp->proxyreq = r->proxyreq;
rp->request_time = r->request_time;
rp->connection = c;
rp->output_filters = c->output_filters;
rp->input_filters = c->input_filters;
rp->proto_output_filters = c->output_filters;
rp->proto_input_filters = c->input_filters;
rp->useragent_ip = c->client_ip;
rp->useragent_addr = c->client_addr;
rp->request_config = ap_create_request_config(pool);
proxy_run_create_req(r, rp);
return rp;
return rv;
}
#endif
static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_conf *conf)
{
@@ -275,7 +228,11 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
apr_bucket_brigade *bb = apr_brigade_create(r->pool, c->bucket_alloc);
len = ap_getline(buffer, sizeof(buffer), rp, 1);
rc = ap_proxygetline(bb, buffer, sizeof(buffer), rp, 0, &len);
if (len == 0) {
rc = ap_proxygetline(bb, buffer, sizeof(buffer), rp, 0, &len);
}
if (len <= 0) {
// oops
@@ -284,11 +241,25 @@ static int uwsgi_response(request_rec *r, proxy_conn_rec *backend, proxy_server_
backend->worker->s->read += len;
if (!apr_date_checkmask(buffer, "HTTP/#.# ###*") || len >= sizeof(buffer)-1) {
if (!apr_date_checkmask(buffer, "HTTP/#.# ###*")) {
// oops
return HTTP_INTERNAL_SERVER_ERROR;
}
int major, minor;
major = buffer[5] - '0';
minor = buffer[7] - '0';
/* If not an HTTP/1 message or
* if the status line was > 8192 bytes
*/
if ((major != 1) || (len >= sizeof(buffer)-1)) {
return ap_proxyerror(r, HTTP_BAD_GATEWAY,
apr_pstrcat(r->pool, "Corrupt status line returned by remote "
"server: ", buffer, NULL));
}
char keepchar = buffer[12];
buffer[12] = '\0';
r->status = atoi(&buffer[9]);
@@ -376,23 +347,12 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
}
// ADD PATH_INFO
#if AP_MODULE_MAGIC_AT_LEAST(20111130,0)
size_t w_len = strlen(worker->s->name);
#else
size_t w_len = strlen(worker->name);
#endif
char *u_path_info = r->filename + 6 + w_len;
int delta = 0;
if (u_path_info[0] != '/') {
delta = 1;
}
int decode_status = ap_unescape_url(url+w_len-delta);
if (decode_status) {
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
"unable to decode uri: %s",
url+w_len-delta);
return HTTP_INTERNAL_SERVER_ERROR;
}
apr_table_add(r->subprocess_env, "PATH_INFO", url+w_len-delta);
+1 -1
View File
@@ -2,7 +2,7 @@
*** uWSGI/mod_uwsgi ***
Copyright 2009-2013 Unbit S.a.s. <info@unbit.it>
Copyright 2009-2012 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
+2 -2
View File
@@ -7,7 +7,7 @@ filename = sys.argv[1]
size = os.path.getsize(filename)
f = open(filename, 'r')
os.write(1, f.read())
print(f.read())
f.close()
os.write(1, (struct.pack("<Q", size)))
print(struct.pack("<Q", size))
+1
View File
@@ -0,0 +1 @@
object file for embedded files will be put here
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = python,gevent,psgi,lua,php,rack,jvm,jwsgi,ring,mono,transformation_toupper,coroae,v8,cgi,xslt,webdav,ssi,ldap,gccgo,rados
inherit = base
+14 -2
View File
@@ -1,12 +1,24 @@
[uwsgi]
xml = auto
ini = true
yaml = true
json = auto
sqlite3 = auto
zeromq = auto
snmp = true
spooler = true
embedded = true
ssl = auto
udp = true
multicast = true
threading = true
minterpreters = true
async = true
ldap = auto
pcre = auto
routing = auto
matheval = auto
alarm = auto
ipv6 = false
debug = false
unbit = false
xml_implementation = libxml2
@@ -17,7 +29,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
as_shared_library = false
locking = auto
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = psgi,coroae
inherit = base
-4
View File
@@ -1,4 +0,0 @@
[uwsgi]
# pypy,jvm,ring,jwsgi
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
inherit = base
-1
View File
@@ -1,4 +1,3 @@
[uwsgi]
main_plugin = python,gevent
inherit = base
debug = false
-4
View File
@@ -1,4 +0,0 @@
[uwsgi]
main_plugin = glusterfs
inherit = base
matheval = false
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = gridfs
inherit = base
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = jvm,jwsgi
inherit = base
-33
View File
@@ -1,33 +0,0 @@
[uwsgi]
xml = false
yaml = false
json = false
zeromq = false
ssl = false
pcre = false
routing = false
matheval = 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 =
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = mono
inherit = base
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin =
inherit = base
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = psgi
inherit = minimal
-32
View File
@@ -1,32 +0,0 @@
[uwsgi]
xml = true
yaml = true
json = true
zeromq = true
ssl = true
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = libyaml
malloc_implementation = libc
extras =
plugins =
bin_name = /usr/lib/libuwsgi.so
append_version = ubuntu
plugin_dir = /usr/lib/uwsgi
embedded_plugins =
as_shared_library = true
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = python
inherit = minimal
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = pypy
inherit = minimal
-6
View File
@@ -1,6 +0,0 @@
[uwsgi]
main_plugin = python,gevent
inherit = base
plugins = jvm,ring
plugin_dir = .
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = rados
inherit = base
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = rack
inherit = minimal
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = jvm,ring
inherit = base
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = rack,rbthreads,fiber
inherit = base
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = jvm,servlet
inherit = base
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin =
inherit = base
+14 -12
View File
@@ -1,32 +1,34 @@
[uwsgi]
xml = true
ini = true
yaml = true
json = false
sqlite3 = false
zeromq = false
ssl = true
snmp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
minterpreters = true
async = true
ldap = true
pcre = true
routing = true
alarm = true
debug = false
unbit = true
xml_implementation = expat
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = /opt/unbit/uwsgi19/lib/libuwsgi.so
bin_name = /opt/unbit/bin/uwsgi
append_version = unbit
plugin_dir = /opt/unbit/uwsgi19/plugins
plugin_dir = /opt/unbit/uwsgi_plugins
embedded_plugins =
as_shared_library = true
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+1
View File
@@ -1,5 +1,6 @@
[uwsgi]
inherit = unbit
json = false
embedded_plugins = python
bin_name = ../bin/uwsgi
plugin_dir = ../bin/uwsgi_plugins
-3
View File
@@ -1,3 +0,0 @@
[uwsgi]
main_plugin = v8
inherit = base
+1
View File
@@ -0,0 +1 @@
the uwsgi handler is included in the official Cherokee distribution
View File
View File
+1 -4
View File
@@ -1,15 +1,12 @@
use POSIX;
use IO::Socket::INET;
use IO::Socket::INET6;
use IO::Socket::UNIX;
my $s = IO::Socket::INET->new(LocalAddr => '127.0.0.1', LocalPort => 1717, Proto => 'tcp', Reuse => 1);
my $s2 = IO::Socket::INET->new(LocalAddr => '127.0.0.1', LocalPort => 3022, Proto => 'tcp', Reuse => 1);
my $s3 = IO::Socket::INET6->new(LocalAddr => '::', LocalPort => 3017, Proto => 'tcp', Reuse => 1);
my $s4 = IO::Socket::UNIX->new(Local => '/tmp/u.sock', Listen => 1);
dup2($s->fileno, 17);
dup2($s2->fileno, 22);
dup2($s3->fileno, 30);
dup2($s4->fileno, 0);
exec './uwsgi','-M', '--socket','fd://17', '--http-socket','fd://22', '--socket','fd://30','--stats',':5001';
exec './uwsgi','-M', '--socket','fd://17', '--http-socket','fd://22', '--socket','fd://30';
-24
View File
@@ -1,24 +0,0 @@
require 'socket'
require 'openssl'
secret = 'ciaociao'
iv = ''
address = '127.0.0.1'
port = 1717
algo = 'bf-cbc'
s = UDPSocket.new
s.bind(address, port)
cipher = OpenSSL::Cipher.new(algo)
cipher.decrypt
cipher.key = secret + ("\0" * (cipher.key_len - secret.length))
cipher.iv = iv + ("0" * (cipher.iv_len - iv.length))
loop do
msg, sender = s.recvfrom(8192)
cipher.reset
begin
puts cipher.update(msg) + cipher.final
rescue
end
end
-61
View File
@@ -1,61 +0,0 @@
"""
Greenlets support
simply --pypy-exec this file to enable PyPy's greenlet mode
Example:
uwsgi --http-socket :9090 --pypy-home /opt/pypy --pypy-wsgi werkzeug.testapp:test_app --pypy-exec contrib/pypy/uwsgi_pypy_greenlets.py --async 8
"""
import greenlet
uwsgi_pypy_greenlets = {}
def uwsgi_pypy_greenlet_wrapper():
lib.async_schedule_to_req_green()
@ffi.callback("void()")
def uwsgi_pypy_greenlet_schedule():
id = lib.uwsgi.wsgi_req.async_id
modifier1 = lib.uwsgi.wsgi_req.uh.modifier1;
# generate a new greenlet
if not lib.uwsgi.wsgi_req.suspended:
uwsgi_pypy_greenlets[id] = greenlet.greenlet(uwsgi_pypy_greenlet_wrapper)
lib.uwsgi.wsgi_req.suspended = 1
# this is called in the main stack
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(ffi.NULL)
# let's switch
uwsgi_pypy_greenlets[id].switch()
# back to the main stack
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(ffi.NULL)
@ffi.callback("void(struct wsgi_request *)")
def uwsgi_pypy_greenlet_switch(wsgi_req):
id = wsgi_req.async_id
modifier1 = wsgi_req.uh.modifier1;
# this is called in the current greenlet
if lib.uwsgi.p[modifier1].suspend:
lib.uwsgi.p[modifier1].suspend(wsgi_req)
uwsgi_pypy_main_greenlet.switch()
# back to the greenlet
if lib.uwsgi.p[modifier1].resume:
lib.uwsgi.p[modifier1].resume(wsgi_req)
# update current running greenlet
lib.uwsgi.wsgi_req = wsgi_req
if lib.uwsgi.async <= 1:
raise Exception("pypy greenlets require async mode !!!")
lib.uwsgi.schedule_to_main = uwsgi_pypy_greenlet_switch
lib.uwsgi.schedule_to_req = uwsgi_pypy_greenlet_schedule
uwsgi_pypy_main_greenlet = greenlet.getcurrent()
-15
View File
@@ -1,15 +0,0 @@
# uWSGI - Emperor
#
description "uWSGI Emperor"
start on runlevel [2345]
stop on runlevel [!2345]
respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
env VASSALS=/etc/uwsgi
exec $BINPATH --emperor $VASSALS --logto $LOGTO
+3 -2
View File
@@ -11,6 +11,7 @@ respawn
env LOGTO=/tmp/uwsgi.log
env BINPATH=/home/foo/uwsgi/uwsgi
# --die-on-term is upstart friendly
exec $BINPATH --die-on-term --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
# --no-orphans avoid workers without master
# --die-on-term could be a good idea
exec $BINPATH --no-orphans --socket :3033 --uid 1001 --gid 1001 --limit-as 256 -w simple_app --logto $LOGTO -M -p 4
+4 -199
View File
@@ -11,29 +11,6 @@ void uwsgi_alarm_func_signal(struct uwsgi_alarm_instance *uai, char *msg, size_t
uwsgi_route_signal(uai->data8);
}
// simply log an alarm
void uwsgi_alarm_init_log(struct uwsgi_alarm_instance *uai) {
}
void uwsgi_alarm_func_log(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
if (msg[len-1] != '\n') {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s\n", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s\n", len, msg);
}
}
else {
if (uai->arg && strlen(uai->arg) > 0) {
uwsgi_log_alarm("] %s %.*s", uai->arg, len, msg);
}
else {
uwsgi_log_alarm("] %.*s", len, msg);
}
}
}
// run a command on alarm
void uwsgi_alarm_init_cmd(struct uwsgi_alarm_instance *uai) {
uai->data_ptr = uai->arg;
@@ -109,7 +86,6 @@ void uwsgi_register_embedded_alarms() {
uwsgi_register_alarm("signal", uwsgi_alarm_init_signal, uwsgi_alarm_func_signal);
uwsgi_register_alarm("cmd", uwsgi_alarm_init_cmd, uwsgi_alarm_func_cmd);
uwsgi_register_alarm("mule", uwsgi_alarm_init_mule, uwsgi_alarm_func_mule);
uwsgi_register_alarm("log", uwsgi_alarm_init_log, uwsgi_alarm_func_log);
}
static int uwsgi_alarm_add(char *name, char *plugin, char *arg) {
@@ -160,7 +136,6 @@ static struct uwsgi_alarm_instance *uwsgi_alarm_get_instance(char *name) {
}
#ifdef UWSGI_PCRE
static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
struct uwsgi_alarm_log *old_ual = NULL, *ual = uwsgi.alarm_logs;
@@ -184,13 +159,11 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
// map instances to the log
char *list = uwsgi_str(alarms);
char *p, *ctx = NULL;
uwsgi_foreach_token(list, ",", p, ctx) {
char *p = strtok(list, ",");
while (p) {
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(p);
if (!uai) {
free(list);
if (!uai)
return -1;
}
struct uwsgi_alarm_ll *old_uall = NULL, *uall = ual->alarms;
while (uall) {
old_uall = uall;
@@ -205,72 +178,14 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
else {
ual->alarms = uall;
}
p = strtok(NULL, ",");
}
free(list);
return 0;
}
#endif
static void uwsgi_alarm_thread_loop(struct uwsgi_thread *ut) {
// add uwsgi_alarm_fd;
struct uwsgi_alarm_fd *uafd = uwsgi.alarm_fds;
while(uafd) {
event_queue_add_fd_read(ut->queue, uafd->fd);
uafd = uafd->next;
}
char *buf = uwsgi_malloc(uwsgi.alarm_msg_size + sizeof(long));
for (;;) {
int interesting_fd = -1;
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret > 0) {
if (interesting_fd == ut->pipe[1]) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.alarm_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
long ptr = 0;
memcpy(&ptr, buf, sizeof(long));
struct uwsgi_alarm_instance *uai = (struct uwsgi_alarm_instance *) ptr;
if (!uai)
break;
uwsgi_alarm_run(uai, msg, msg_size);
}
}
// check for alarm_fd
else {
uafd = uwsgi.alarm_fds;
int fd_read = 0;
while(uafd) {
if (interesting_fd == uafd->fd) {
if (fd_read) goto raise;
size_t remains = uafd->buf_len;
while(remains) {
ssize_t len = read(uafd->fd, uafd->buf + (uafd->buf_len-remains), remains);
if (len <= 0) {
uwsgi_error("[uwsgi-alarm-fd]/read()");
uwsgi_log("[uwsgi-alarm-fd] i will stop monitoring fd %d\n", uafd->fd);
event_queue_del_fd(ut->queue, uafd->fd, event_queue_read());
break;
}
remains-=len;
}
fd_read = 1;
raise:
uwsgi_alarm_run(uafd->alarm, uafd->msg, uafd->msg_len);
}
uafd = uafd->next;
}
}
}
}
free(buf);
}
// initialize alarms, instances and log regexps
void uwsgi_alarms_init() {
if (!uwsgi.master_process) return;
// first of all, create instance of alarms
struct uwsgi_string_list *usl = uwsgi.alarm_list;
while (usl) {
@@ -297,40 +212,6 @@ void uwsgi_alarms_init() {
usl = usl->next;
}
if (!uwsgi.alarm_instances) return;
// map alarm file descriptors
usl = uwsgi.alarm_fd_list;
while(usl) {
char *space0 = strchr(usl->value, ' ');
if (!space0) {
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
exit(1);
}
*space0 = 0;
size_t buf_len = 1;
char *space1 = strchr(space0+1, ' ');
if (!space1) {
uwsgi_log("invalid alarm-fd syntax: %s\n", usl->value);
exit(1);
}
char *colon = strchr(space0+1, ':');
if (colon) {
buf_len = strtoul(colon+1, NULL, 10);
*colon = 0;
}
int fd = atoi(space0+1);
uwsgi_add_alarm_fd(fd, usl->value, buf_len, space1+1, strlen(space1+1));
*space0 = ' ';
*space1 = ' ';
if (colon) {
*colon = ':';
}
usl = usl->next;
}
#ifdef UWSGI_PCRE
// then map log-alarm
usl = uwsgi.alarm_logs_list;
while (usl) {
@@ -350,20 +231,8 @@ void uwsgi_alarms_init() {
usl = usl->next;
}
#endif
}
void uwsgi_alarm_thread_start() {
if (!uwsgi.alarm_instances) return;
// start the alarm_thread
uwsgi.alarm_thread = uwsgi_thread_new(uwsgi_alarm_thread_loop);
if (!uwsgi.alarm_thread) {
uwsgi_log("unable to spawn alarm thread\n");
exit(1);
}
}
#ifdef UWSGI_PCRE
// check if a log should raise an alarm
void uwsgi_alarm_log_check(char *msg, size_t len) {
if (!uwsgi_strncmp(msg, len, "[uwsgi-alarm", 12))
@@ -381,7 +250,6 @@ void uwsgi_alarm_log_check(char *msg, size_t len) {
ual = ual->next;
}
}
#endif
// call the alarm func
void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
@@ -397,7 +265,6 @@ void uwsgi_alarm_run(struct uwsgi_alarm_instance *uai, char *msg, size_t len) {
uai->last_msg_size = len;
}
#ifdef UWSGI_PCRE
// call the alarms mapped to a log line
void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
struct uwsgi_alarm_ll *uall = ual->alarms;
@@ -406,65 +273,3 @@ void uwsgi_alarm_log_run(struct uwsgi_alarm_log *ual, char *msg, size_t len) {
uall = uall->next;
}
}
#endif
// this is the api function workers,mules and whatever you want can call from code
void uwsgi_alarm_trigger(char *alarm_instance_name, char *msg, size_t len) {
if (!uwsgi.alarm_thread) return;
if (len > uwsgi.alarm_msg_size) return;
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm_instance_name);
if (!uai) return;
struct iovec iov[2];
iov[0].iov_base = &uai;
iov[0].iov_len = sizeof(long);
iov[1].iov_base = msg;
iov[1].iov_len = len;
// now send the message to the alarm thread
if (writev(uwsgi.alarm_thread->pipe[0], iov, 2) != (ssize_t) (len+sizeof(long))) {
uwsgi_error("[uwsgi-alarm-error] uwsgi_alarm_trigger()/writev()");
}
}
struct uwsgi_alarm_fd *uwsgi_add_alarm_fd(int fd, char *alarm, size_t buf_len, char *msg, size_t msg_len) {
struct uwsgi_alarm_fd *old_uafd = NULL, *uafd = uwsgi.alarm_fds;
struct uwsgi_alarm_instance *uai = uwsgi_alarm_get_instance(alarm);
if (!uai) {
uwsgi_log("unable to find alarm \"%s\"\n", alarm);
exit(1);
}
if (!buf_len) buf_len = 1;
while(uafd) {
// check if an equal alarm has been added
if (uafd->fd == fd && uafd->alarm == uai) {
return uafd;
}
old_uafd = uafd;
uafd = uafd->next;
}
uafd = uwsgi_calloc(sizeof(struct uwsgi_alarm_fd));
uafd->fd = fd;
uafd->buf = uwsgi_malloc(buf_len);
uafd->buf_len = buf_len;
uafd->msg = msg;
uafd->msg_len = msg_len;
uafd->alarm = uai;
if (!old_uafd) {
uwsgi.alarm_fds = uafd;
}
else {
old_uafd->next = uafd;
}
// avoid the fd to be closed
uwsgi_add_safe_fd(fd);
uwsgi_log("[uwsgi-alarm] added fd %d\n", fd);
return uafd;
}
+128 -196
View File
@@ -1,32 +1,7 @@
#include <uwsgi.h>
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
/*
This is a general purpose async loop engine (it expects a coroutine based approach)
You can see it as an hub holding the following structures:
1) the runqueue, cores ready to be run are appended in this list
2) the fd list, this is a list of monitored file descriptors, a core can wait for all the file descriptors it needs
3) the timeout value, if set the current core will timeout aftert he specified number of seconds (unless an event cancel it)
IMPORTANT: this is not a callback based engine !!!
*/
// this is called whenever a new connection is ready, but there are no cores to handle it
void uwsgi_async_queue_is_full(time_t now) {
if (now > uwsgi.async_queue_is_full) {
uwsgi_log_verbose("[DANGER] async queue is full !!!\n");
uwsgi.async_queue_is_full = now;
}
}
void uwsgi_async_init() {
int i;
@@ -40,15 +15,12 @@ void uwsgi_async_init() {
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
// a stack of unused cores
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
// fill it with default values
for (i = 0; i < uwsgi.async; i++) {
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
}
// the first available core is the last one
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
}
@@ -61,7 +33,7 @@ struct wsgi_request *find_wsgi_req_by_fd(int fd) {
return uwsgi.async_waiting_fd_table[fd];
}
static void runqueue_remove(struct uwsgi_async_request *u_request) {
void runqueue_remove(struct uwsgi_async_request *u_request) {
struct uwsgi_async_request *parent = u_request->prev;
struct uwsgi_async_request *child = u_request->next;
@@ -73,7 +45,7 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
child->prev = parent;
}
if (u_request == uwsgi.async_runqueue) {
if (parent == NULL) {
uwsgi.async_runqueue = child;
}
@@ -82,33 +54,33 @@ static void runqueue_remove(struct uwsgi_async_request *u_request) {
}
free(u_request);
uwsgi.async_runqueue_cnt--;
}
static void runqueue_push(struct wsgi_request *wsgi_req) {
void runqueue_push(struct wsgi_request *wsgi_req) {
// do not push the same request in the runqueue
struct uwsgi_async_request *uar = uwsgi.async_runqueue;
while(uar) {
if (uar->wsgi_req == wsgi_req) return;
uar = uar->next;
}
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = NULL;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
struct uwsgi_async_request *uar;
if (uwsgi.async_runqueue == NULL) {
uwsgi.async_runqueue = uar;
// empty runqueue, create a new one
uwsgi.async_runqueue = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uwsgi.async_runqueue->next = NULL;
uwsgi.async_runqueue->prev = NULL;
uwsgi.async_runqueue->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last = uwsgi.async_runqueue;
}
else {
uar->prev = uwsgi.async_runqueue_last;
uar = uwsgi_malloc(sizeof(struct uwsgi_async_request));
uar->prev = uwsgi.async_runqueue_last;
uar->next = NULL;
uar->wsgi_req = wsgi_req;
uwsgi.async_runqueue_last->next = uar;
uwsgi.async_runqueue_last = uar;
}
if (uwsgi.async_runqueue_last) {
uwsgi.async_runqueue_last->next = uar;
}
uwsgi.async_runqueue_last = uar;
uwsgi.async_runqueue_cnt++;
}
struct wsgi_request *find_first_available_wsgi_req() {
@@ -124,28 +96,12 @@ struct wsgi_request *find_first_available_wsgi_req() {
return wsgi_req;
}
void async_reset_request(struct wsgi_request *wsgi_req) {
if (wsgi_req->async_timeout) {
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
}
struct uwsgi_async_fd *uaf = wsgi_req->waiting_fds;
while (uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
struct uwsgi_async_fd *current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
}
static void async_expire_timeouts(uint64_t now) {
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
uint64_t current_time = (uint64_t) uwsgi_now();
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for (;;) {
@@ -155,13 +111,24 @@ static void async_expire_timeouts(uint64_t now) {
if (urbt == NULL)
return;
if (urbt->value <= now) {
if (urbt->value <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
// reset teh request
async_reset_request(wsgi_req);
// push it in the runqueue
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, wsgi_req->async_timeout);
free(wsgi_req->async_timeout);
wsgi_req->async_timeout = NULL;
uaf = wsgi_req->waiting_fds;
// remove fds from monitoring (no problem modifying the queue here, as the function is executed only when there are no fd ready)
while (uaf) {
event_queue_del_fd(uwsgi.async_queue, uaf->fd, uaf->event);
uwsgi.async_waiting_fd_table[uaf->fd] = NULL;
current_uaf = uaf;
uaf = current_uaf->next;
free(current_uaf);
}
wsgi_req->waiting_fds = NULL;
// put th request in the runqueue
runqueue_push(wsgi_req);
continue;
}
@@ -171,14 +138,14 @@ static void async_expire_timeouts(uint64_t now) {
}
int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
void async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0)
return -1;
return;
// find last slot
// find first slot
while (uad) {
last_uad = uad;
uad = uad->next;
@@ -201,47 +168,26 @@ int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
async_add_timeout(wsgi_req, timeout);
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
wsgi_req->async_force_again = 1;
return event_queue_add_fd_read(uwsgi.async_queue, fd);
}
event_queue_add_fd_read(uwsgi.async_queue, fd);
static int async_wait_fd_read(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_read(wsgi_req, fd, timeout)) {
return -1;
}
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(wsgi_req);
}
if (wsgi_req->async_timed_out) {
wsgi_req->async_timed_out = 0;
return 0;
}
return 1;
}
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
wsgi_req->async_ready_fd = 0;
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
wsgi_req->async_timeout = uwsgi_add_rb_timer(uwsgi.rb_async_timeouts, uwsgi_now() + timeout, wsgi_req);
}
}
int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
void async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
if (fd < 0)
return -1;
return;
// find last slot
// find first slot
while (uad) {
last_uad = uad;
uad = uad->next;
@@ -265,72 +211,12 @@ int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
}
uwsgi.async_waiting_fd_table[fd] = wsgi_req;
wsgi_req->async_force_again = 1;
return event_queue_add_fd_write(uwsgi.async_queue, fd);
}
event_queue_add_fd_write(uwsgi.async_queue, fd);
static int async_wait_fd_write(int fd, int timeout) {
struct wsgi_request *wsgi_req = current_wsgi_req();
wsgi_req->async_ready_fd = 0;
if (async_add_fd_write(wsgi_req, fd, timeout)) {
return -1;
}
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(wsgi_req);
}
if (wsgi_req->async_timed_out) {
wsgi_req->async_timed_out = 0;
return 0;
}
return 1;
}
void async_schedule_to_req(void) {
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
// a trick to avoid calling routes again
uwsgi.wsgi_req->is_routing = 1;
#endif
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
goto end;
}
if (uwsgi.schedule_to_main) {
uwsgi.schedule_to_main(uwsgi.wsgi_req);
}
return;
end:
async_reset_request(uwsgi.wsgi_req);
uwsgi_close_request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_status = UWSGI_OK;
}
void async_schedule_to_req_green(void) {
#ifdef UWSGI_ROUTING
if (uwsgi_apply_routes(uwsgi.wsgi_req) == UWSGI_ROUTE_BREAK) {
goto end;
}
#endif
for(;;) {
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
break;
}
uwsgi.wsgi_req->switches++;
// switch after each yield
uwsgi.schedule_to_main(uwsgi.wsgi_req);
}
#ifdef UWSGI_ROUTING
end:
#endif
async_reset_request(uwsgi.wsgi_req);
uwsgi_close_request(uwsgi.wsgi_req);
uwsgi.wsgi_req->async_status = UWSGI_OK;
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
}
void async_loop() {
@@ -340,23 +226,22 @@ void async_loop() {
exit(1);
}
struct uwsgi_async_fd *tmp_uaf;
int interesting_fd, i;
struct uwsgi_rb_timer *min_timeout;
int timeout;
int is_a_new_connection;
int proto_parser_status;
uint64_t now;
time_t now, last_now = 0;
struct uwsgi_async_request *current_request = NULL;
static struct uwsgi_async_request *current_request = NULL, *next_async_request = NULL;
void *events = event_queue_alloc(64);
struct uwsgi_socket *uwsgi_sock;
uwsgi.async_runqueue = NULL;
uwsgi.wait_write_hook = async_wait_fd_write;
uwsgi.wait_read_hook = async_wait_fd_read;
uwsgi.async_runqueue_cnt = 0;
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
@@ -367,22 +252,20 @@ void async_loop() {
if (!uwsgi.schedule_to_req)
uwsgi.schedule_to_req = async_schedule_to_req;
if (!uwsgi.schedule_to_main) {
uwsgi_log("*** DANGER *** async mode without coroutine/greenthread engine loaded !!!\n");
}
while (uwsgi.workers[uwsgi.mywid].manage_next_request) {
now = (uint64_t) uwsgi_now();
if (uwsgi.async_runqueue) {
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
else {
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->value - now;
timeout = min_timeout->value - uwsgi_now();
if (timeout <= 0) {
async_expire_timeouts(now);
async_expire_timeouts();
timeout = 0;
}
}
@@ -393,10 +276,9 @@ void async_loop() {
uwsgi.async_nevents = event_queue_wait_multi(uwsgi.async_queue, timeout, events, 64);
now = (uint64_t) uwsgi_now();
// timeout ???
if (uwsgi.async_nevents == 0) {
async_expire_timeouts(now);
async_expire_timeouts();
}
@@ -404,15 +286,16 @@ void async_loop() {
// manage events
interesting_fd = event_queue_interesting_fd(events, i);
// signals are executed in the main stack... in the future we could have dedicated stacks for them
if (uwsgi.signal_socket > -1 && (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket)) {
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
continue;
}
is_a_new_connection = 0;
// new request coming in ?
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
@@ -422,17 +305,32 @@ void async_loop() {
uwsgi.wsgi_req = find_first_available_wsgi_req();
if (uwsgi.wsgi_req == NULL) {
uwsgi_async_queue_is_full((time_t)now);
now = uwsgi_now();
if (now > last_now) {
uwsgi_log("async queue is full !!!\n");
last_now = now;
}
break;
}
// on error re-insert the request in the queue
wsgi_req_setup(uwsgi.wsgi_req, uwsgi.wsgi_req->async_id, uwsgi_sock);
if (wsgi_req_simple_accept(uwsgi.wsgi_req, interesting_fd)) {
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
// on linux we do not need to reset the socket to blocking state
#ifndef __linux__
/* re-set blocking socket */
int arg = uwsgi_sock->arg;
arg &= (~O_NONBLOCK);
if (fcntl(uwsgi.wsgi_req->poll.fd, F_SETFL, arg) < 0) {
uwsgi_error("fcntl()");
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
break;
}
#endif
if (wsgi_req_async_recv(uwsgi.wsgi_req)) {
uwsgi.async_queue_unused_ptr++;
@@ -440,9 +338,6 @@ void async_loop() {
break;
}
// by default the core is in UWSGI_AGAIN mode
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
// some protocol (like zeromq) do not need additional parsing, just push it in the runqueue
if (uwsgi.wsgi_req->do_not_add_to_async_queue) {
runqueue_push(uwsgi.wsgi_req);
}
@@ -459,7 +354,9 @@ void async_loop() {
if (uwsgi.wsgi_req) {
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
// reset timeout
async_reset_request(uwsgi.wsgi_req);
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
// parsing complete
if (!proto_parser_status) {
// remove fd from event poll and fd proto table
@@ -470,6 +367,8 @@ void async_loop() {
continue;
}
else if (proto_parser_status < 0) {
if (proto_parser_status == -1)
uwsgi_log("error parsing request\n");
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
close(interesting_fd);
continue;
@@ -479,7 +378,7 @@ void async_loop() {
continue;
}
// app-registered event
// app event
uwsgi.wsgi_req = find_wsgi_req_by_fd(interesting_fd);
// unknown fd, remove it (for safety)
if (uwsgi.wsgi_req == NULL) {
@@ -488,45 +387,78 @@ void async_loop() {
}
// remove all the fd monitors and timeout
async_reset_request(uwsgi.wsgi_req);
while (uwsgi.wsgi_req->waiting_fds) {
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
uwsgi.wsgi_req->async_ready_fd = 1;
uwsgi.wsgi_req->async_last_ready_fd = interesting_fd;
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
break;
}
}
// event queue managed, give cpu to runqueue
current_request = uwsgi.async_runqueue;
if (!current_request)
current_request = uwsgi.async_runqueue;
while(current_request) {
// current_request could be nulled on error/end of request
struct uwsgi_async_request *next_request = current_request->next;
if (uwsgi.async_runqueue_cnt) {
uwsgi.wsgi_req = current_request->wsgi_req;
uwsgi.schedule_to_req();
uwsgi.wsgi_req->switches++;
next_async_request = current_request->next;
// request ended ?
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) {
// remove from the runqueue
// remove all the monitored fds and timeout
while (uwsgi.wsgi_req->waiting_fds) {
tmp_uaf = uwsgi.wsgi_req->waiting_fds;
uwsgi.async_waiting_fd_table[tmp_uaf->fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, tmp_uaf->fd, tmp_uaf->event);
uwsgi.wsgi_req->waiting_fds = tmp_uaf->next;
free(tmp_uaf);
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
uwsgi_del_rb_timer(uwsgi.rb_async_timeouts, uwsgi.wsgi_req->async_timeout);
free(uwsgi.wsgi_req->async_timeout);
uwsgi.wsgi_req->async_timeout = NULL;
}
// remove from the list
runqueue_remove(current_request);
uwsgi_close_request(uwsgi.wsgi_req);
// push wsgi_request in the unused stack
uwsgi.async_queue_unused_ptr++;
uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req;
}
else if (uwsgi.wsgi_req->waiting_fds || uwsgi.wsgi_req->async_timeout) {
// remove this request from the runqueue
// remove this request from suspended list
runqueue_remove(current_request);
}
current_request = next_request;
current_request = next_async_request;
}
}
}
+7 -279
View File
@@ -3,9 +3,6 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_buffer *uwsgi_buffer_new(size_t len) {
#ifdef UWSGI_DEBUG_BUFFER
uwsgi_log("[uwsgi-buffer] allocating a new buffer of %llu\n", (unsigned long long) len);
#endif
struct uwsgi_buffer *ub = uwsgi_calloc(sizeof(struct uwsgi_buffer));
if (len) {
@@ -51,50 +48,6 @@ int uwsgi_buffer_ensure(struct uwsgi_buffer *ub, size_t len) {
return 0;
}
int uwsgi_buffer_insert(struct uwsgi_buffer *ub, size_t pos, char *buf, size_t len) {
size_t to_move = (ub->pos-pos);
if (uwsgi_buffer_ensure(ub, len)) return -1;
memmove(ub->buf+pos+len, ub->buf+pos, to_move);
memcpy(ub->buf+pos, buf, len);
ub->pos += len;
return 0;
}
int uwsgi_buffer_insert_chunked(struct uwsgi_buffer *ub, size_t pos, size_t len) {
// 0xFFFFFFFFFFFFFFFF\r\n\0
char chunked[19];
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
if (ret <= 0 || ret > 19) {
return -1;
}
return uwsgi_buffer_insert(ub, pos, chunked, ret);
}
int uwsgi_buffer_append_chunked(struct uwsgi_buffer *ub, size_t len) {
// 0xFFFFFFFFFFFFFFFF\r\n\0
char chunked[19];
int ret = snprintf(chunked, 19, "%X\r\n", (unsigned int) len);
if (ret <= 0 || ret > 19) {
return -1;
}
return uwsgi_buffer_append(ub, chunked, ret);
}
int uwsgi_buffer_decapitate(struct uwsgi_buffer *ub, size_t len) {
if (len > ub->pos) return -1;
memmove(ub->buf, ub->buf + len, ub->pos-len);
ub->pos = ub->pos-len;
return 0;
}
int uwsgi_buffer_byte(struct uwsgi_buffer *ub, char byte) {
return uwsgi_buffer_append(ub, &byte, 1);
}
int uwsgi_buffer_u8(struct uwsgi_buffer *ub, uint8_t u8) {
return uwsgi_buffer_append(ub, (char *) &u8, 1);
}
int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
@@ -124,204 +77,12 @@ int uwsgi_buffer_append(struct uwsgi_buffer *ub, char *buf, size_t len) {
return 0;
}
int uwsgi_buffer_append_json(struct uwsgi_buffer *ub, char *buf, size_t len) {
// need to escape \ and "
size_t i;
for(i=0;i<len;i++) {
if (buf[i] == '"') {
if (uwsgi_buffer_append(ub, "\\\"", 2)) return -1;
}
else if (buf[i] == '\\') {
if (uwsgi_buffer_append(ub, "\\\\", 2)) return -1;
}
else {
if (uwsgi_buffer_append(ub, buf+i, 1)) return -1;
}
}
return 0;
}
int uwsgi_buffer_u16le(struct uwsgi_buffer *ub, uint16_t num) {
uint8_t buf[2];
buf[0] = (uint8_t) (num & 0xff);
buf[1] = (uint8_t) ((num >> 8) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 2);
}
int uwsgi_buffer_u16be(struct uwsgi_buffer *ub, uint16_t num) {
uint8_t buf[2];
buf[1] = (uint8_t) (num & 0xff);
buf[0] = (uint8_t) ((num >> 8) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 2);
}
int uwsgi_buffer_u24be(struct uwsgi_buffer *ub, uint32_t num) {
uint8_t buf[3];
buf[2] = (uint8_t) (num & 0xff);
buf[1] = (uint8_t) ((num >> 8) & 0xff);
buf[0] = (uint8_t) ((num >> 16) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 3);
}
int uwsgi_buffer_u32be(struct uwsgi_buffer *ub, uint32_t num) {
uint8_t buf[4];
buf[3] = (uint8_t) (num & 0xff);
buf[2] = (uint8_t) ((num >> 8) & 0xff);
buf[1] = (uint8_t) ((num >> 16) & 0xff);
buf[0] = (uint8_t) ((num >> 24) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 4);
}
int uwsgi_buffer_f32be(struct uwsgi_buffer *ub, float num) {
uint8_t buf[4];
uint32_t *pnum = (uint32_t *) &num;
buf[3] = (uint8_t) (*pnum & 0xff);
buf[2] = (uint8_t) ((*pnum >> 8) & 0xff);
buf[1] = (uint8_t) ((*pnum >> 16) & 0xff);
buf[0] = (uint8_t) ((*pnum >> 24) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 4);
}
int uwsgi_buffer_u32le(struct uwsgi_buffer *ub, uint32_t num) {
uint8_t buf[4];
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);
return uwsgi_buffer_append(ub, (char *) buf, 4);
}
int uwsgi_buffer_u64be(struct uwsgi_buffer *ub, uint64_t num) {
uint8_t buf[8];
buf[7] = (uint8_t) (num & 0xff);
buf[6] = (uint8_t) ((num >> 8) & 0xff);
buf[5] = (uint8_t) ((num >> 16) & 0xff);
buf[4] = (uint8_t) ((num >> 24) & 0xff);
buf[3] = (uint8_t) ((num >> 32) & 0xff);
buf[2] = (uint8_t) ((num >> 40) & 0xff);
buf[1] = (uint8_t) ((num >> 48) & 0xff);
buf[0] = (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];
uint64_t *pnum = (uint64_t *) &num;
buf[7] = (uint8_t) (*pnum & 0xff);
buf[6] = (uint8_t) ((*pnum >> 8) & 0xff);
buf[5] = (uint8_t) ((*pnum >> 16) & 0xff);
buf[4] = (uint8_t) ((*pnum >> 24) & 0xff);
buf[3] = (uint8_t) ((*pnum >> 32) & 0xff);
buf[2] = (uint8_t) ((*pnum >> 40) & 0xff);
buf[1] = (uint8_t) ((*pnum >> 48) & 0xff);
buf[0] = (uint8_t) ((*pnum >> 56) & 0xff);
return uwsgi_buffer_append(ub, (char *) buf, 8);
}
int uwsgi_buffer_append_ipv4(struct uwsgi_buffer *ub, void *addr) {
char ip[INET_ADDRSTRLEN];
if (!inet_ntop(AF_INET, addr, ip, INET_ADDRSTRLEN)) {
uwsgi_error("uwsgi_buffer_append_ipv4() -> inet_ntop()");
return -1;
}
return uwsgi_buffer_append(ub, ip, strlen(ip));
}
int uwsgi_buffer_num64(struct uwsgi_buffer *ub, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%lld", (long long) num);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
return uwsgi_buffer_append(ub, buf, ret);
}
int uwsgi_buffer_append_keyval(struct uwsgi_buffer *ub, char *key, uint16_t keylen, char *val, uint16_t vallen) {
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
if (uwsgi_buffer_u16le(ub, vallen)) return -1;
return uwsgi_buffer_append(ub, val, vallen);
}
int uwsgi_buffer_append_keyval32(struct uwsgi_buffer *ub, char *key, uint32_t keylen, char *val, uint32_t vallen) {
if (uwsgi_buffer_u32be(ub, keylen)) return -1;
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
if (uwsgi_buffer_u32be(ub, vallen)) return -1;
return uwsgi_buffer_append(ub, val, vallen);
}
int uwsgi_buffer_append_keynum(struct uwsgi_buffer *ub, char *key, uint16_t keylen, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
if (uwsgi_buffer_u16le(ub, ret)) return -1;
return uwsgi_buffer_append(ub, buf, ret);
}
int uwsgi_buffer_append_valnum(struct uwsgi_buffer *ub, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, (sizeof(UMAX64_STR)+1), "%lld", (long long) num);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
if (uwsgi_buffer_u16le(ub, ret)) return -1;
return uwsgi_buffer_append(ub, buf, ret);
}
int uwsgi_buffer_append_keyipv4(struct uwsgi_buffer *ub, char *key, uint16_t keylen, void *addr) {
if (uwsgi_buffer_u16le(ub, keylen)) return -1;
if (uwsgi_buffer_append(ub, key, keylen)) return -1;
if (uwsgi_buffer_u16le(ub, 15)) return -1;
char *ptr = ub->buf + (ub->pos - 2);
if (uwsgi_buffer_append_ipv4(ub, addr)) return -1;
// fix the size
*ptr = ((ub->buf+ub->pos) - (ptr+2));
return 0;
}
int uwsgi_buffer_append_base64(struct uwsgi_buffer *ub, char *s, size_t len) {
size_t b64_len = 0;
char *b64 = uwsgi_base64_encode(s, len, &b64_len);
if (!b64) return -1;
int ret = uwsgi_buffer_append(ub, b64, b64_len);
free(b64);
return ret;
}
void uwsgi_buffer_destroy(struct uwsgi_buffer *ub) {
#ifdef UWSGI_DEBUG_BUFFER
uwsgi_log("[uwsgi-buffer] destroying buffer of %llu bytes\n", (unsigned long long) ub->len);
if (ub->freed) {
uwsgi_log("[uwsgi-buffer][BUG] buffer at %p already destroyed !!!\n", ub);
}
ub->freed = 1;
#endif
if (ub->buf)
free(ub->buf);
free(ub);
}
ssize_t uwsgi_buffer_write_simple(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub) {
size_t remains = ub->pos;
while(remains) {
ssize_t len = write(wsgi_req->fd, ub->buf + (ub->pos - remains), remains);
if (len <= 0) {
return len;
}
remains -= len;
}
return ub->pos;
}
int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
size_t remains = ub->pos;
char *ptr = ub->buf;
@@ -354,45 +115,12 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
return 0;
}
int uwsgi_buffer_set_uh(struct uwsgi_buffer *ub, uint8_t modifier1, uint8_t modifier2) {
if (ub->pos < 4) return -1;
ub->buf[0] = modifier1;
ub->buf[1] = (uint8_t) ((ub->pos - 4) & 0xff);
ub->buf[2] = (uint8_t) (((ub->pos - 4) >> 8) & 0xff);
ub->buf[3] = modifier2;
return 0;
int uwsgi_buffer_num64(struct uwsgi_buffer *ub, int64_t num) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%lld", (long long) num);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
return -1;
}
return uwsgi_buffer_append(ub, buf, ret);
}
struct uwsgi_buffer *uwsgi_buffer_from_file(char *filename) {
struct stat st;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
return NULL;
}
if (fstat(fd, &st)) {
close(fd);
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(st.st_size);
ssize_t len = read(fd, ub->buf, st.st_size);
close(fd);
if (len != st.st_size) {
uwsgi_buffer_destroy(ub);
return NULL;
}
ub->pos = len;
return ub;
}
void uwsgi_buffer_map(struct uwsgi_buffer *ub, char *buf, size_t len) {
if (ub->buf) {
free(ub->buf);
}
ub->buf = buf;
ub->pos = len;
ub->len = len;
}
+231 -1716
View File
File diff suppressed because it is too large Load Diff
-162
View File
@@ -1,162 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
Chunked input implementation
--chunked-input-limit <bytes> (default 1MB)
--chunked-input-timeout <s> (default --socket-timeout)
chunk = uwsgi.chunked_read([timeout])
timeout = -1 (wait forever)
timeout = 0 (default)
*/
static ssize_t uwsgi_chunked_input_recv(struct wsgi_request *wsgi_req, int timeout, int nb) {
if (timeout == 0) timeout = uwsgi.chunked_input_timeout;
if (timeout == 0) timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
int ret = -1;
for(;;) {
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
if (rlen > 0) return rlen;
if (rlen == 0) return -1;
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
if (nb) return -1;
goto wait;
}
uwsgi_error("uwsgi_chunked_input_recv()");
return -1;
}
wait:
ret = uwsgi.wait_read_hook(wsgi_req->fd, timeout);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->chunked_input_buf->buf + wsgi_req->chunked_input_buf->pos, wsgi_req->chunked_input_buf->len - wsgi_req->chunked_input_buf->pos);
if (rlen > 0) return rlen;
if (rlen <= 0) return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_chunked_input_recv()");
}
return -1;
}
return -1;
}
static ssize_t uwsgi_chunked_readline(struct wsgi_request *wsgi_req) {
size_t i;
int found = 0;
for(i=0;i<wsgi_req->chunked_input_buf->pos;i++) {
if (found) {
if (wsgi_req->chunked_input_buf->buf[i] == '\n') {
// strtoul will stop at \r
size_t num = strtoul(wsgi_req->chunked_input_buf->buf, NULL, 16);
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, i+1)) return -1;
return num;
}
return -1;
}
if ((wsgi_req->chunked_input_buf->buf[i] >= '0' && wsgi_req->chunked_input_buf->buf[i] <= '9') ||
(wsgi_req->chunked_input_buf->buf[i] >= 'a' && wsgi_req->chunked_input_buf->buf[i] <= 'z') ||
(wsgi_req->chunked_input_buf->buf[i] >= 'A' && wsgi_req->chunked_input_buf->buf[i] <= 'Z')) continue;
if (wsgi_req->chunked_input_buf->buf[i] == '\r') { found = 1; continue; }
return -1;
}
return -2;
}
/*
0 -> waiting for \r\n
1 -> waiting for whole body
*/
char *uwsgi_chunked_read(struct wsgi_request *wsgi_req, size_t *len, int timeout, int nb) {
if (!wsgi_req->chunked_input_buf) {
wsgi_req->chunked_input_buf = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->chunked_input_buf->limit = uwsgi.chunked_input_limit;
}
// the whole chunk stream has been consumed
if (wsgi_req->chunked_input_complete) {
*len = 0;
return wsgi_req->chunked_input_buf->buf;
}
if (wsgi_req->chunked_input_decapitate > 0) {
if (uwsgi_buffer_decapitate(wsgi_req->chunked_input_buf, wsgi_req->chunked_input_decapitate)) return NULL;
wsgi_req->chunked_input_decapitate = 0;
}
for(;;) {
if (wsgi_req->chunked_input_need > 0 || wsgi_req->chunked_input_buf->pos == 0) {
if (uwsgi_buffer_ensure(wsgi_req->chunked_input_buf, UMAX((uint64_t)uwsgi.page_size, wsgi_req->chunked_input_need))) return NULL;
ssize_t rlen = uwsgi_chunked_input_recv(wsgi_req, timeout, nb);
if (rlen <= 0) return NULL;
// update buffer position
wsgi_req->chunked_input_buf->pos += rlen;
if (wsgi_req->chunked_input_need > 0) {
if ((size_t)rlen > wsgi_req->chunked_input_need) {
wsgi_req->chunked_input_need = 0;
}
else {
wsgi_req->chunked_input_need -= rlen;
}
}
}
if (wsgi_req->chunked_input_need > 0) continue;
// ok we have a frame, let's parse it
if (wsgi_req->chunked_input_buf->pos > 0) {
switch(wsgi_req->chunked_input_parser_status) {
case 0:
wsgi_req->chunked_input_chunk_len = uwsgi_chunked_readline(wsgi_req);
if (wsgi_req->chunked_input_chunk_len == -2) {
wsgi_req->chunked_input_need++;
break;
}
else if (wsgi_req->chunked_input_chunk_len < 0) {
return NULL;
}
else if (wsgi_req->chunked_input_chunk_len == 0) {
*len = 0;
wsgi_req->chunked_input_complete = 1;
return wsgi_req->chunked_input_buf->buf;
}
// if here the buffer has been already decapitated
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
wsgi_req->chunked_input_parser_status = 1;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
return wsgi_req->chunked_input_buf->buf;
case 1:
if ((size_t)(wsgi_req->chunked_input_chunk_len+2) > wsgi_req->chunked_input_buf->pos) {
wsgi_req->chunked_input_need = (wsgi_req->chunked_input_chunk_len+2) - wsgi_req->chunked_input_buf->pos;
break;
}
*len = wsgi_req->chunked_input_chunk_len;
wsgi_req->chunked_input_decapitate = wsgi_req->chunked_input_chunk_len+2;
wsgi_req->chunked_input_parser_status = 0;
return wsgi_req->chunked_input_buf->buf;
}
}
}
}
-1
View File
@@ -1 +0,0 @@
int main() {}
+464
View File
@@ -0,0 +1,464 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_UDP
static void cluster_manage_opt(char *key, uint16_t keylen, char *value, uint16_t vallen, void *foobar) {
add_exported_option(uwsgi_concat2n(key, keylen, "", 0), uwsgi_concat2n(value, vallen, "", 0), 0);
}
void cluster_setup() {
int rlen;
// get cluster configuration
if (uwsgi.cluster != NULL) {
// get multicast socket
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
// ask for cluster options only if bot pre-existent options are set
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
// now wait max 60 seconds and resend multicast request every 10 seconds
for (;;) {
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
continue;
}
waitfd:
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
if (rlen < 0) {
break;
}
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
uwsgi_configure();
goto options_parsed;
}
else {
goto waitfd;
}
}
}
}
options_parsed:
if (!uwsgi.cluster_nodes)
uwsgi_cluster_add_me();
}
}
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
#ifdef UWSGI_DEBUG
uwsgi_log("adding node\n");
#endif
tcp_port = strchr(nucn->name, ':');
#ifndef UWSGI_ZEROMQ
if (tcp_port == NULL) {
#else
char *zmq_dash = strchr(nucn->name, '-');
if (tcp_port == NULL && zmq_dash == NULL) {
#endif
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
return;
}
// first check for already present node
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0) {
if (!strcmp(ucn->name, nucn->name)) {
ucn->status = UWSGI_NODE_OK;
ucn->last_seen = uwsgi_now();
// update requests
ucn->requests = nucn->requests;
return;
}
}
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] == 0) {
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
ucn->workers = nucn->workers;
ucn->ucn_addr.sin_family = AF_INET;
if (tcp_port) {
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
tcp_port[0] = 0;
}
if (nucn->name[0] == 0) {
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", nucn->name);
#endif
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
}
ucn->type = type;
// here memory can be freed, as it is allocated by uwsgi_concat2n
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
tcp_port[0] = ':';
}
ucn->last_seen = uwsgi_now();
ucn->requests = nucn->requests;
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
return;
}
}
uwsgi_log("unable to add node %s\n", nucn->name);
}
int uwsgi_cluster_add_me() {
const char *key1 = "hostname";
const char *key2 = "address";
const char *key3 = "workers";
const char *key4 = "requests";
char *ptrbuf;
uint16_t ustrlen;
char numproc[6];
#ifdef UWSGI_ZEROMQ
char uuid_zmq_str[37];
uuid_t uuid_zmq;
if (!uwsgi.sockets && !uwsgi.zeromq) {
#else
if (!uwsgi.sockets) {
#endif
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
snprintf(numproc, 6, "%d", uwsgi.numproc);
size_t len;
if (uwsgi.sockets) {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, uuid_zmq_str);
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#endif
else {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
char *buf = uwsgi_malloc(len);
ptrbuf = buf;
ustrlen = strlen(key1);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key1, strlen(key1));
ptrbuf += strlen(key1);
ustrlen = strlen(uwsgi.hostname);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
ptrbuf += strlen(uwsgi.hostname);
if (uwsgi.sockets && uwsgi.sockets->name) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uwsgi.sockets->name);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
ptrbuf += strlen(uwsgi.sockets->name);
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uuid_zmq_str);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
ptrbuf += strlen(uuid_zmq_str);
}
#endif
ustrlen = strlen(key3);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key3, strlen(key3));
ptrbuf += strlen(key3);
ustrlen = strlen(numproc);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, numproc, strlen(numproc));
ptrbuf += strlen(numproc);
ustrlen = strlen(key4);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key4, strlen(key4));
ptrbuf += strlen(key4);
ustrlen = 1;
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, "0", 1);
ptrbuf += 1;
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
free(buf);
#ifdef UWSGI_DEBUG
uwsgi_log("add_me() successfull\n");
#endif
return 0;
}
int uwsgi_cluster_join(char *name) {
int fd;
char *cp;
int broadcast = 0;
if (name[0] == ':') {
fd = bind_to_udp(name, 0, 1);
broadcast = 1;
}
else {
fd = bind_to_udp(name, 1, 0);
}
if (fd >= 0) {
cp = strchr(name, ':');
cp[0] = 0;
uwsgi.mc_cluster_addr.sin_family = AF_INET;
if (broadcast) {
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
}
else {
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
}
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
cp[0] = ':';
// announce my presence to all the nodes
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
}
else {
exit(1);
}
return fd;
}
char *uwsgi_cluster_best_node() {
int i;
int best_node = -1;
struct uwsgi_cluster_node *ucn;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
if (best_node == -1) {
best_node = i;
}
else {
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
best_node = i;
}
}
}
}
if (best_node == -1) {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = uwsgi_now();
return uwsgi.shared->nodes[best_node].name;
}
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
void manage_cluster_message(char *cluster_opt_buf, int cluster_opt_size) {
struct uwsgi_cluster_node nucn;
switch (uwsgi.workers[0].cores[0].req.uh.modifier1) {
case 95:
memset(&nucn, 0, sizeof(struct uwsgi_cluster_node));
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.workers[0].cores[0].req.uh.pktsize);
#endif
uwsgi_hooked_parse(uwsgi.workers[0].cores[0].req.buffer, uwsgi.workers[0].cores[0].req.uh.pktsize, manage_cluster_announce, &nucn);
if (nucn.name[0] != 0) {
uwsgi_cluster_add_node(&nucn, CLUSTER_NODE_DYNAMIC);
}
break;
case 96:
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.workers[0].cores[0].req.uh.pktsize);
#endif
uwsgi_log_verbose("%.*s\n", uwsgi.workers[0].cores[0].req.uh.pktsize, uwsgi.workers[0].cores[0].req.buffer);
break;
case 98:
if (kill(getpid(), SIGHUP)) {
uwsgi_error("kill()");
}
break;
case 99:
if (uwsgi.cluster_nodes)
break;
if (uwsgi.workers[0].cores[0].req.uh.modifier2 == 0) {
uwsgi_log("requested configuration data, sending %d bytes\n", cluster_opt_size);
sendto(uwsgi.cluster_fd, cluster_opt_buf, cluster_opt_size, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr));
}
break;
case 73:
#ifdef __BIG_ENDIAN__
uwsgi.workers[0].cores[0].req.uh.pktsize = uwsgi_swap16(uwsgi.workers[0].cores[0].req.uh.pktsize);
#endif
uwsgi_log_verbose("[uWSGI cluster %s] new node available: %.*s\n", uwsgi.cluster, uwsgi.workers[0].cores[0].req.uh.pktsize, uwsgi.workers[0].cores[0].req.buffer);
break;
}
}
#endif
char *uwsgi_setup_clusterbuf(size_t * size) {
size_t cluster_opt_size = 4;
int i;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
//uwsgi_log("%s\n", uwsgi.exported_opts[i]->key);
cluster_opt_size += 2 + strlen(uwsgi.exported_opts[i]->key);
if (uwsgi.exported_opts[i]->value) {
cluster_opt_size += 2 + strlen(uwsgi.exported_opts[i]->value);
}
else {
cluster_opt_size += 2 + 1;
}
}
//uwsgi_log("cluster opts size: %d\n", cluster_opt_size);
char *cluster_opt_buf = uwsgi_malloc(cluster_opt_size);
struct uwsgi_header *uh = (struct uwsgi_header *) cluster_opt_buf;
uh->modifier1 = 99;
uh->pktsize = cluster_opt_size - 4;
uh->modifier2 = 1;
#ifdef __BIG_ENDIAN__
uh->pktsize = uwsgi_swap16(uh->pktsize);
#endif
char *cptrbuf = cluster_opt_buf + 4;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
//uwsgi_log("%s\n", uwsgi.exported_opts[i]->key);
uint16_t ustrlen = strlen(uwsgi.exported_opts[i]->key);
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(cptrbuf, uwsgi.exported_opts[i]->key, ustrlen);
cptrbuf += ustrlen;
if (uwsgi.exported_opts[i]->value) {
ustrlen = strlen(uwsgi.exported_opts[i]->value);
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(cptrbuf, uwsgi.exported_opts[i]->value, ustrlen);
}
else {
ustrlen = 1;
*cptrbuf++ = (uint8_t) (ustrlen & 0xff);
*cptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
*cptrbuf = '1';
}
cptrbuf += ustrlen;
}
return cluster_opt_buf;
}
-631
View File
@@ -1,631 +0,0 @@
#include <uwsgi.h>
/*
pluggable configuration system
*/
extern struct uwsgi_server uwsgi;
struct uwsgi_configurator *uwsgi_register_configurator(char *name, void (*func)(char *, char **)) {
struct uwsgi_configurator *old_uc = NULL,*uc = uwsgi.configurators;
while(uc) {
if (!strcmp(uc->name, name)) {
return uc;
}
old_uc = uc;
uc = uc->next;
}
uc = uwsgi_calloc(sizeof(struct uwsgi_configurator));
uc->name = name;
uc->func = func;
if (old_uc) {
old_uc->next = uc;
}
else {
uwsgi.configurators = uc;
}
return uc;
}
int uwsgi_logic_opt_if_exists(char *key, char *value) {
if (uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_exists(char *key, char *value) {
if (!uwsgi_file_exists(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_for(char *key, char *value) {
char *p, *ctx = NULL;
uwsgi_foreach_token(uwsgi.logic_opt_data, " ", p, ctx) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
}
return 1;
}
int uwsgi_logic_opt_for_glob(char *key, char *value) {
glob_t g;
int i;
if (glob(uwsgi.logic_opt_data, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("uwsgi_logic_opt_for_glob()");
return 0;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", g.gl_pathv[i]), 0);
}
globfree(&g);
return 1;
}
int uwsgi_logic_opt_for_times(char *key, char *value) {
int num = atoi(uwsgi.logic_opt_data);
int i;
char str_num[11];
for (i = 1; i <= num; i++) {
int ret = uwsgi_num2str2(i, str_num);
// security check
if (ret < 0 || ret > 11) {
exit(1);
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", str_num), 0);
}
return 1;
}
int uwsgi_logic_opt_if_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_opt(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = uwsgi_get_exported_opt(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (strcmp(equal + 1, p))
return 0;
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_env(char *key, char *value) {
// check for env-value syntax
char *equal = strchr(uwsgi.logic_opt_data, '=');
if (equal)
*equal = 0;
char *p = getenv(uwsgi.logic_opt_data);
if (equal)
*equal = '=';
if (p) {
if (equal) {
if (!strcmp(equal + 1, p))
return 0;
}
else {
return 0;
}
}
add_exported_option(key, uwsgi_substitute(value, "%(_)", p), 0);
return 1;
}
int uwsgi_logic_opt_if_reload(char *key, char *value) {
if (uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
if (!uwsgi.is_a_reload) {
add_exported_option(key, value, 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_file(char *key, char *value) {
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_file(char *key, char *value) {
if (!uwsgi_is_file(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_dir(char *key, char *value) {
if (uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_dir(char *key, char *value) {
if (!uwsgi_is_dir(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_plugin(char *key, char *value) {
if (plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_logic_opt_if_not_plugin(char *key, char *value) {
if (!plugin_already_loaded(uwsgi.logic_opt_data)) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", uwsgi.logic_opt_data), 0);
return 1;
}
return 0;
}
int uwsgi_count_options(struct uwsgi_option *uopt) {
struct uwsgi_option *aopt;
int count = 0;
while ((aopt = uopt)) {
if (!aopt->name)
break;
count++;
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;
int round = 0;
retry:
round++;
if (round > 2) goto end;
op = uwsgi.options;
while (op->name) {
if (!strcmp(name, op->name)) {
return op;
}
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;
while (blacklist) {
if (!strcmp(key, blacklist->value)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
blacklist = blacklist->next;
}
if (whitelist) {
int allowed = 0;
while (whitelist) {
if (!strcmp(key, whitelist->value)) {
allowed = 1;
break;
}
whitelist = whitelist->next;
}
if (!allowed) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.blacklist_context) {
if (uwsgi_list_has_str(uwsgi.blacklist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
exit(1);
}
}
if (uwsgi.whitelist_context) {
if (!uwsgi_list_has_str(uwsgi.whitelist_context, key)) {
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
exit(1);
}
}
if (uwsgi.logic_opt_running)
goto add;
if (!strcmp(key, "end") || !strcmp(key, "endfor") || !strcmp(key, "endif")) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt = NULL;
uwsgi.logic_opt_arg = NULL;
uwsgi.logic_opt_cycles = 0;
uwsgi.logic_opt_data = NULL;
}
if (uwsgi.logic_opt) {
if (uwsgi.logic_opt_data) {
free(uwsgi.logic_opt_data);
}
uwsgi.logic_opt_data = uwsgi_str(uwsgi.logic_opt_arg);
uwsgi.logic_opt_cycles++;
uwsgi.logic_opt_running = 1;
uwsgi.logic_opt(key, value);
uwsgi.logic_opt_running = 0;
return;
}
add:
if (!uwsgi.exported_opts) {
uwsgi.exported_opts = uwsgi_malloc(sizeof(struct uwsgi_opt *));
}
else {
uwsgi.exported_opts = realloc(uwsgi.exported_opts, sizeof(struct uwsgi_opt *) * (uwsgi.exported_opts_cnt + 1));
if (!uwsgi.exported_opts) {
uwsgi_error("realloc()");
exit(1);
}
}
int id = uwsgi.exported_opts_cnt;
uwsgi.exported_opts[id] = uwsgi_malloc(sizeof(struct uwsgi_opt));
uwsgi.exported_opts[id]->key = key;
uwsgi.exported_opts[id]->value = value;
uwsgi.exported_opts[id]->configured = configured;
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 ?
if (op->flags & UWSGI_OPT_MASTER) {
uwsgi.master_process = 1;
}
// requires log_master ?
if (op->flags & UWSGI_OPT_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
}
if (op->flags & UWSGI_OPT_REQ_LOG_MASTER) {
uwsgi.master_process = 1;
uwsgi.log_master = 1;
uwsgi.req_log_master = 1;
}
// requires threads ?
if (op->flags & UWSGI_OPT_THREADS) {
uwsgi.has_threads = 1;
}
// requires cheaper mode ?
if (op->flags & UWSGI_OPT_CHEAPER) {
uwsgi.cheaper = 1;
}
// requires virtualhosting ?
if (op->flags & UWSGI_OPT_VHOST) {
uwsgi.vhost = 1;
}
// requires memusage ?
if (op->flags & UWSGI_OPT_MEMORY) {
uwsgi.force_get_memusage = 1;
}
// requires auto procname ?
if (op->flags & UWSGI_OPT_PROCNAME) {
uwsgi.auto_procname = 1;
}
// requires lazy ?
if (op->flags & UWSGI_OPT_LAZY) {
uwsgi.lazy = 1;
}
// requires no_initial ?
if (op->flags & UWSGI_OPT_NO_INITIAL) {
uwsgi.no_initial_output = 1;
}
// requires no_server ?
if (op->flags & UWSGI_OPT_NO_SERVER) {
uwsgi.no_server = 1;
}
// requires post_buffering ?
if (op->flags & UWSGI_OPT_POST_BUFFERING) {
if (!uwsgi.post_buffering)
uwsgi.post_buffering = 4096;
}
// requires building mime dict ?
if (op->flags & UWSGI_OPT_MIME) {
uwsgi.build_mime_dict = 1;
}
// immediate ?
if (op->flags & UWSGI_OPT_IMMEDIATE) {
op->func(key, value, op->data);
uwsgi.exported_opts[id]->configured = 1;
}
}
}
void uwsgi_fallback_config() {
if (uwsgi.fallback_config && uwsgi.last_exit_code == 1) {
uwsgi_log_verbose("!!! %s (pid: %d) exited with status %d !!!\n", uwsgi.binary_path, (int) getpid(), uwsgi.last_exit_code);
uwsgi_log_verbose("!!! Fallback config to %s !!!\n", uwsgi.fallback_config);
char *argv[3];
argv[0] = uwsgi.binary_path;
argv[1] = uwsgi.fallback_config;
argv[2] = NULL;
execvp(uwsgi.binary_path, argv);
uwsgi_error("execvp()");
// 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);
}
-81
View File
@@ -1,81 +0,0 @@
#include <uwsgi.h>
/*
cookie management functions (mainly used by the internal routing subsystem)
*/
static char *check_cookie(char *cookie, uint16_t cookie_len, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t orig_cookie_len = cookie_len-1;
// first lstrip white spaces
char *ptr = cookie;
uint16_t i;
for(i=0;i<cookie_len;i++) {
if (isspace((int)ptr[i])) {
cookie++;
cookie_len--;
}
else {
break;
}
}
// then rstrip (skipping the first char...)
for(i=orig_cookie_len;i>0;i--) {
if (isspace((int)ptr[i])) {
cookie_len--;
}
else {
break;
}
}
// now search for the first equal sign
char *equal = memchr(cookie, '=', cookie_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, cookie, equal-cookie)) {
return NULL;
}
cookie_len -= (equal-cookie)+1;
if (cookie_len == 0) return NULL;
*vallen = cookie_len;
return equal+1;
}
char *uwsgi_get_cookie(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *cookie = wsgi_req->cookie;
uint16_t cookie_len = 0;
char *ptr = wsgi_req->cookie;
//start splitting by ;
for(i=0;i<wsgi_req->cookie_len;i++) {
if (!cookie) {
cookie = ptr + i;
}
if (ptr[i] == ';') {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
cookie_len = 0;
cookie = NULL;
}
else {
cookie_len++;
}
}
if (cookie_len > 0) {
char *value = check_cookie(cookie, cookie_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
-320
View File
@@ -1,320 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
struct uwsgi_cron *uwsgi_cron_add(char *crontab) {
int i;
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
if (sscanf(crontab, "%d %d %d %d %d %n", &uc->minute, &uc->hour, &uc->day, &uc->month, &uc->week, &i) != 5) {
uwsgi_log("invalid cron syntax\n");
exit(1);
}
uc->command = crontab + i;
uc->pid = -1;
return uc;
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
uwsgi_cron_add(value);
}
void uwsgi_opt_add_unique_cron(char *opt, char *value, void *foobar) {
struct uwsgi_cron *uc = uwsgi_cron_add(value);
uc->unique = 1;
}
#ifdef UWSGI_SSL
void uwsgi_opt_add_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
}
void uwsgi_opt_add_unique_legion_cron(char *opt, char *value, void *foobar) {
char *space = strchr(value, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be prefixed with a legion name\n", opt);
exit(1);
}
char *legion = uwsgi_concat2n(value, space-value, "", 0);
struct uwsgi_cron *uc = uwsgi_cron_add(space+1);
uc->legion = legion;
uc->unique = 1;
}
#endif
void uwsgi_opt_add_cron2(char *opt, char *value, void *foobar) {
char *c_minute = NULL;
char *c_hour = NULL;
char *c_day = NULL;
char *c_month = NULL;
char *c_week = NULL;
char *c_unique = NULL;
char *c_harakiri = NULL;
char *c_legion = NULL;
char *c_command = value;
char *space = strchr(value, ' ');
if (space) {
if (uwsgi_str_contains(value, space - value, '=')) {
// --cron2 key=val command
*space = 0;
c_command = space + 1;
}
// no point in parsing key=val list if there is none
if (uwsgi_kvlist_parse(value, strlen(value), ',', '=',
"minute", &c_minute,
"hour", &c_hour,
"day", &c_day,
"month", &c_month,
"week", &c_week,
"unique", &c_unique,
"harakiri", &c_harakiri,
"legion", &c_legion,
NULL)) {
uwsgi_log("unable to parse cron definition: %s\n", value);
exit(1);
}
}
else {
if (uwsgi_str_contains(value, strlen(value), '=')) {
// --cron2 key=val
uwsgi_log("unable to parse cron definition: %s\n", value);
exit(1);
}
}
struct uwsgi_cron *old_uc, *uc = uwsgi.crons;
if (!uc) {
uc = uwsgi_malloc(sizeof(struct uwsgi_cron));
uwsgi.crons = uc;
}
else {
old_uc = uc;
while (uc->next) {
uc = uc->next;
old_uc = uc;
}
old_uc->next = uwsgi_malloc(sizeof(struct uwsgi_cron));
uc = old_uc->next;
}
memset(uc, 0, sizeof(struct uwsgi_cron));
uc->command = c_command;
if (!uc->command) {
uwsgi_log("[uwsgi-cron] invalid command in cron definition: %s\n", value);
exit(1);
}
// defaults
uc->minute = -1;
uc->hour = -1;
uc->day = -1;
uc->month = -1;
uc->week = -1;
uc->unique = 0;
uc->mercy = 0;
uc->harakiri = 0;
uc->pid = -1;
#ifdef UWSGI_SSL
uc->legion = c_legion;
#endif
if (c_minute)
uc->minute = atoi(c_minute);
if (c_hour)
uc->hour = atoi(c_hour);
if (c_day)
uc->day = atoi(c_day);
if (c_month)
uc->month = atoi(c_month);
if (c_week)
uc->week = atoi(c_week);
if (c_unique)
uc->unique = atoi(c_unique);
if (c_harakiri) {
if (atoi(c_harakiri)) {
// harakiri > 0
uc->mercy = atoi(c_harakiri);
}
else {
// harakiri == 0
uc->mercy = -1;
}
}
else if (uwsgi.cron_harakiri) {
uc->harakiri = uwsgi.cron_harakiri;
}
}
int uwsgi_signal_add_cron(uint8_t sig, int minute, int hour, int day, int month, int week) {
if (!uwsgi.master_process)
return -1;
uwsgi_lock(uwsgi.cron_table_lock);
if (ushared->cron_cnt < MAX_CRONS) {
ushared->cron[ushared->cron_cnt].sig = sig;
ushared->cron[ushared->cron_cnt].minute = minute;
ushared->cron[ushared->cron_cnt].hour = hour;
ushared->cron[ushared->cron_cnt].day = day;
ushared->cron[ushared->cron_cnt].month = month;
ushared->cron[ushared->cron_cnt].week = week;
ushared->cron_cnt++;
}
else {
uwsgi_log("you can register max %d cron !!!\n", MAX_CRONS);
uwsgi_unlock(uwsgi.cron_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.cron_table_lock);
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, ucron->minute, ucron->hour, ucron->day, ucron->month, ucron->week);
if (run_task == 1) {
// date match, signal it ?
if (now - ucron->last_job >= 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = now;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
uwsgi_error("uwsgi_manage_command_cron()/localtime()");
return;
}
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
#ifdef UWSGI_SSL
// check for legion cron
if (current_cron->legion) {
if (!uwsgi_legion_i_am_the_lord(current_cron->legion))
goto next;
}
#endif
// skip unique crons that are still running
if (current_cron->unique && current_cron->pid >= 0)
goto next;
int run_task = uwsgi_cron_task_needs_execution(uwsgi_cron_delta, current_cron->minute, current_cron->hour, current_cron->day, current_cron->month, current_cron->week);
if (run_task == 1) {
// date match, run command ?
if (now - current_cron->last_job >= 60) {
//call command
if (current_cron->command) {
if (current_cron->func) {
current_cron->func(current_cron, now);
}
else {
pid_t pid = uwsgi_run_command(current_cron->command, NULL, -1);
if (pid >= 0) {
current_cron->pid = pid;
current_cron->started_at = now;
uwsgi_log_verbose("[uwsgi-cron] running \"%s\" (pid %d)\n", current_cron->command, current_cron->pid);
if (current_cron->mercy) {
//uwsgi_cron->mercy can be negative to inform master that harakiri should be disabled for this cron
if (current_cron->mercy > 0)
current_cron->harakiri = now + current_cron->mercy;
}
else if (uwsgi.cron_harakiri)
current_cron->harakiri = now + uwsgi.cron_harakiri;
}
}
}
current_cron->last_job = now;
}
}
next:
current_cron = current_cron->next;
}
}
+26 -133
View File
@@ -1,4 +1,4 @@
#include <uwsgi.h>
#include "../uwsgi.h"
extern struct uwsgi_server uwsgi;
@@ -42,31 +42,6 @@ void uwsgi_daemons_smart_check() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
#ifdef UWSGI_SSL
if (ud->legion) {
if (uwsgi_legion_i_am_the_lord(ud->legion)) {
// lord, spawn if not running
if (ud->pid <= 0) {
uwsgi_spawn_daemon(ud);
}
}
else {
// not lord, kill daemon if running
if (ud->pid > 0) {
if (!kill(ud->pid, 0)) {
uwsgi_log("[uwsgi_daemons] stopping legion \"%s\" daemon: %s (pid: %d)\n", ud->legion, ud->command, ud->pid);
kill(-ud->pid, SIGTERM);
}
else {
// pid already died
ud->pid = -1;
}
}
ud = ud->next;
continue;
}
}
#endif
if (ud->pidfile) {
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
if (checked_pid <= 0) {
@@ -77,14 +52,8 @@ void uwsgi_daemons_smart_check() {
else {
ud->pidfile_checks++;
if (ud->pidfile_checks >= (unsigned int) ud->freq) {
if (!ud->has_daemonized) {
uwsgi_log_verbose("[uwsgi-daemons] \"%s\" (pid: %d) did not daemonize !!!\n", ud->command, (int) ud->pid);
ud->pidfile_checks = 0;
}
else {
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
uwsgi_spawn_daemon(ud);
}
uwsgi_log("[uwsgi-daemons] found changed pidfile for \"%s\" (old_pid: %d new_pid: %d)\n", ud->command, (int) ud->pid, (int) checked_pid);
uwsgi_spawn_daemon(ud);
}
}
}
@@ -101,24 +70,13 @@ void uwsgi_daemons_smart_check() {
}
}
// this function is called when a dumb daemon dies and we do not want to respawn it
// this function is called when a dumb daemon dies and we do not wat to respawn it
int uwsgi_daemon_check_pid_death(pid_t diedpid) {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (ud->pid == diedpid) {
if (!ud->pidfile) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
ud->pid = -1;
return -1;
}
else {
if (!ud->has_daemonized) {
ud->has_daemonized = 1;
}
else {
uwsgi_log("[uwsgi-daemons] BUG !!! daemon \"%s\" has already daemonized !!!\n", ud->command);
}
}
if (ud->pid == diedpid && !ud->pidfile) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
return -1;
}
ud = ud->next;
}
@@ -129,20 +87,7 @@ int uwsgi_daemon_check_pid_death(pid_t diedpid) {
int uwsgi_daemon_check_pid_reload(pid_t diedpid) {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
#ifdef UWSGI_SSL
if (ud->pid == diedpid && ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
// part of legion but not lord, don't respawn
ud->pid = -1;
uwsgi_log("uwsgi-daemons] legion \"%s\" daemon \"%s\" (pid: %d) annihilated\n", ud->legion, ud->command, (int) diedpid);
ud = ud->next;
continue;
}
#endif
if (ud->pid == diedpid && !ud->pidfile) {
if (ud->control) {
gracefully_kill_them_all(0);
return 0;
}
uwsgi_spawn_daemon(ud);
return 1;
}
@@ -188,20 +133,6 @@ void uwsgi_daemons_spawn_all() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
if (!ud->registered) {
#ifdef UWSGI_SSL
if (ud->legion && !uwsgi_legion_i_am_the_lord(ud->legion)) {
// part of legion, register but don't spawn it yet
if (ud->pidfile) {
ud->pid = uwsgi_check_pidfile(ud->pidfile);
if (ud->pid > 0)
uwsgi_log("[uwsgi-daemons] found valid/active pidfile for \"%s\" (pid: %d)\n", ud->command, (int) ud->pid);
}
ud->registered = 1;
ud = ud->next;
continue;
}
#endif
ud->registered = 1;
if (ud->pidfile) {
int checked_pid = uwsgi_check_pidfile(ud->pidfile);
if (checked_pid <= 0) {
@@ -215,6 +146,7 @@ void uwsgi_daemons_spawn_all() {
else {
uwsgi_spawn_daemon(ud);
}
ud->registered = 1;
}
ud = ud->next;
}
@@ -224,31 +156,8 @@ void uwsgi_daemons_spawn_all() {
void uwsgi_detach_daemons() {
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
#ifdef UWSGI_SSL
// stop any legion daemon, doesn't matter if dumb or smart
if (ud->pid > 0 && (ud->legion || !ud->pidfile)) {
#else
// stop only dumb daemons
if (ud->pid > 0 && !ud->pidfile) {
#endif
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
// try to gracefully stop daemon, kill it if it won't die
// if mercy is not set than wait up to 3 seconds
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
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);
kill(-ud->pid, SIGKILL);
break;
}
}
// unregister daemon to prevent it from being respawned
ud->registered = 0;
}
if (ud->pid > 0 && !ud->pidfile)
kill(-ud->pid, SIGKILL);
ud = ud->next;
}
}
@@ -256,9 +165,7 @@ void uwsgi_detach_daemons() {
void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
// skip unregistered daemons
if (!ud->registered) return;
int devnull = -1;
int throttle = 0;
if (uwsgi.current_time - ud->last_spawn <= 3) {
@@ -272,7 +179,6 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
}
if (pid > 0) {
ud->has_daemonized = 0;
ud->pid = pid;
ud->status = 1;
ud->pidfile_checks = 0;
@@ -302,9 +208,18 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
uwsgi_write_pidfile(ud->pidfile);
}
if (!uwsgi.daemons_honour_stdin) {
// /dev/null will became stdin
uwsgi_remap_fd(0, "/dev/null");
// /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);
}
if (setsid() < 0) {
@@ -344,26 +259,11 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
char *pidfile = NULL;
int daemonize = 0;
int freq = 10;
char *space = NULL;
char *command = uwsgi_str(value);
#ifdef UWSGI_SSL
char *legion = NULL;
if (!uwsgi_starts_with(opt, strlen(command), "legion-", 7)) {
space = strchr(command, ' ');
if (!space) {
uwsgi_log("invalid legion daemon syntax: %s\n", command);
exit(1);
}
*space = 0;
legion = command;
command = space+1;
}
#endif
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon") || !strcmp(opt, "legion-smart-attach-daemon2")) {
space = strchr(command, ' ');
if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2")) {
char *space = strchr(command, ' ');
if (!space) {
uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
exit(1);
@@ -377,7 +277,7 @@ void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {
freq = atoi(comma + 1);
}
command = space + 1;
if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) {
if (!strcmp(opt, "smart-attach-daemon2")) {
daemonize = 1;
}
}
@@ -406,13 +306,6 @@ 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
uwsgi.daemons_cnt++;
+142 -790
View File
File diff suppressed because it is too large Load Diff
-45
View File
@@ -1,45 +0,0 @@
#include <uwsgi.h>
// generate internal server error message
void uwsgi_500(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
}
void uwsgi_404(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
}
void uwsgi_403(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
}
void uwsgi_redirect_to_slash(struct wsgi_request *wsgi_req) {
char *redirect = NULL;
size_t redirect_len = 0;
if (uwsgi_response_prepare_headers(wsgi_req, "301 Moved Permanently", 21)) return;
if (uwsgi_response_add_connection_close(wsgi_req)) return;
if (wsgi_req->query_string_len == 0) {
redirect = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "/", 1);
redirect_len = wsgi_req->path_info_len + 1;
}
else {
redirect = uwsgi_concat3n(wsgi_req->path_info, wsgi_req->path_info_len, "/?", 2, wsgi_req->query_string, wsgi_req->query_string_len);
redirect_len = wsgi_req->path_info_len + 2 + wsgi_req->query_string_len;
}
uwsgi_response_add_header(wsgi_req, "Location", 8, redirect, redirect_len);
free(redirect);
return;
}
+14 -271
View File
@@ -2,233 +2,6 @@
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_USE_POLL
#define UWSGI_EVENT_IN POLLIN
#define UWSGI_EVENT_OUT POLLOUT
int uwsgi_poll_event_queue_max = 0;
struct uwsgi_poll_event {
int nevents;
int max_events;
pthread_mutex_t lock;
struct pollfd *poll;
};
struct uwsgi_poll_event **uwsgi_poll_event_queue;
// all of the public functions must be heavy locked
static int uwsgi_poll_fd_is_registered(struct uwsgi_poll_event *upe, int fd) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
return 1;
}
}
return 0;
}
static int uwsgi_poll_fd_add(struct uwsgi_poll_event *upe, int fd, int event) {
int pos = upe->nevents;
if (pos > upe->max_events) return -1;
upe->poll[pos].fd = fd;
upe->poll[pos].events = event;
upe->nevents++;
return 0;
}
static int uwsgi_poll_fd_del(struct uwsgi_poll_event *upe, int fd) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
if (i < upe->nevents-1) {
memcpy(&upe->poll[i], &upe->poll[i+1], sizeof(struct uwsgi_poll_event) * (upe->nevents - (i+1)));
}
upe->nevents--;
return 0;
}
}
return -1;
}
static void uwsgi_poll_queue_rebuild(struct uwsgi_poll_event *upe) {
// we need to check if some file descriptor is no more valid
int i;
for(i=0;i<upe->nevents;i++) {
if (!uwsgi_valid_fd(upe->poll[i].fd)) {
uwsgi_poll_fd_del(upe, upe->poll[i].fd);
}
}
}
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
uwsgi_poll_queue_rebuild(upe);
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
if (ret > 0) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].revents) {
*interesting_fd = upe->poll[i].fd;
pthread_mutex_unlock(&upe->lock);
return 1;
}
}
}
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_init() {
if (!uwsgi_poll_event_queue) {
uwsgi_poll_event_queue = uwsgi_calloc(sizeof(struct uwsgi_poll_event *) * uwsgi.max_fd);
}
int eq = uwsgi_poll_event_queue_max;
uwsgi_poll_event_queue[eq] = uwsgi_calloc(sizeof(struct uwsgi_poll_event));
uwsgi_poll_event_queue_max++;
uwsgi_poll_event_queue[eq]->poll = uwsgi_malloc(sizeof(struct pollfd) * uwsgi.max_fd);
uwsgi_poll_event_queue[eq]->max_events = uwsgi.max_fd;
pthread_mutex_init(&uwsgi_poll_event_queue[eq]->lock, NULL);
return eq;
}
void *event_queue_alloc(int nevents) {
return uwsgi_calloc(sizeof(struct pollfd) * nevents);
}
int event_queue_interesting_fd_is_read(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
if (upoll->revents & POLLIN) {
return 1;
}
return 0;
}
int event_queue_fd_write_to_readwrite(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
upe->poll[i].events = POLLIN|POLLOUT;
pthread_mutex_unlock(&upe->lock);
return 0;
}
}
pthread_mutex_unlock(&upe->lock);
return -1;
}
int event_queue_fd_read_to_readwrite(int eq, int fd) {
return event_queue_fd_write_to_readwrite(eq, fd);
}
int event_queue_interesting_fd_is_write(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
if (upoll->revents & POLLOUT) {
return 1;
}
return 0;
}
int event_queue_add_fd_read(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
if (uwsgi_poll_fd_is_registered(upe, fd)) {
pthread_mutex_unlock(&upe->lock);
return 0;
}
int ret = uwsgi_poll_fd_add(upe, fd, POLLIN);
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_add_fd_write(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
if (uwsgi_poll_fd_is_registered(upe, fd)) {
pthread_mutex_unlock(&upe->lock);
return 0;
}
int ret = uwsgi_poll_fd_add(upe, fd, POLLOUT);
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_del_fd(int eq, int fd, int event) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int ret = uwsgi_poll_fd_del(upe, fd);
pthread_mutex_unlock(&upe->lock);
return ret;
}
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
uwsgi_poll_queue_rebuild(upe);
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
int cnt = 0;
if (ret > 0) {
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].revents) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[cnt];
upoll->fd = upe->poll[i].fd;
upoll->revents = upe->poll[i].revents;
upoll->events = upe->poll[i].events;
cnt++;
}
}
}
pthread_mutex_unlock(&upe->lock);
if (ret <= 0) return ret;
return cnt;
}
int event_queue_interesting_fd_has_error(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
if (upoll->revents & POLLERR || upoll->revents & POLLHUP || upoll->revents & POLLNVAL) {
return 1;
}
return 0;
}
int event_queue_interesting_fd(void *events, int id) {
struct pollfd *pevents = (struct pollfd *)events;
struct pollfd *upoll = &pevents[id];
return upoll->fd;
}
int event_queue_fd_write_to_read(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
upe->poll[i].events = POLLIN;
pthread_mutex_unlock(&upe->lock);
return 0;
}
}
pthread_mutex_unlock(&upe->lock);
return -1;
}
int event_queue_fd_read_to_write(int eq, int fd) {
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
pthread_mutex_lock(&upe->lock);
int i;
for(i=0;i<upe->nevents;i++) {
if (upe->poll[i].fd == fd) {
upe->poll[i].events = POLLOUT;
pthread_mutex_unlock(&upe->lock);
return 0;
}
}
pthread_mutex_unlock(&upe->lock);
return -1;
}
#endif
#ifdef UWSGI_EVENT_USE_PORT
#include <port.h>
@@ -260,7 +33,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
@@ -271,7 +44,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
int event_queue_fd_read_to_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
uwsgi_error("port_associate");
return -1;
}
@@ -282,7 +55,7 @@ int event_queue_fd_read_to_write(int eq, int fd) {
int event_queue_fd_readwrite_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
uwsgi_error("port_associate");
return -1;
}
@@ -293,7 +66,7 @@ int event_queue_fd_readwrite_to_read(int eq, int fd) {
int event_queue_fd_readwrite_to_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
uwsgi_error("port_associate");
return -1;
}
@@ -304,7 +77,7 @@ int event_queue_fd_readwrite_to_write(int eq, int fd) {
int event_queue_fd_write_to_readwrite(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
uwsgi_error("port_associate");
return -1;
}
@@ -315,7 +88,7 @@ int event_queue_fd_write_to_readwrite(int eq, int fd) {
int event_queue_fd_read_to_readwrite(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
uwsgi_error("port_associate");
return -1;
}
@@ -335,7 +108,7 @@ int event_queue_interesting_fd_has_error(void *events, int id) {
int event_queue_interesting_fd_is_read(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
if (pe[id].portev_events == POLLIN) {
if (pe[id].portev_events = POLLIN) {
return 1;
}
return 0;
@@ -351,7 +124,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
int event_queue_add_fd_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *) eq)) {
uwsgi_error("port_associate");
return -1;
}
@@ -361,7 +134,7 @@ int event_queue_add_fd_read(int eq, int fd) {
int event_queue_add_fd_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
uwsgi_error("port_associate");
return -1;
}
@@ -376,16 +149,12 @@ void *event_queue_alloc(int nevents) {
int event_queue_interesting_fd(void *events, int id) {
port_event_t *pe = (port_event_t *) events;
#ifdef PORT_SOURCE_FILE
if (pe[id].portev_source == PORT_SOURCE_FILE || pe[id].portev_source == PORT_SOURCE_TIMER) {
#else
if (pe[id].portev_source == PORT_SOURCE_TIMER) {
#endif
return (long) pe[id].portev_user;
}
int fd = (int) pe[id].portev_object;
int eq = (long) pe[id].portev_user;
int eq = (int) pe[id].portev_user;
if (pe[id].portev_events == POLLOUT) {
event_queue_add_fd_write(eq, fd);
@@ -402,7 +171,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
int ret;
uint_t nget = 1;
timespec_t ts;
if (timeout >= 0) {
ts.tv_sec = timeout;
@@ -421,18 +189,6 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
return 0;
}
uint_t i;
port_event_t *pe = (port_event_t *) events;
for(i=0;i<nget;i++) {
port_event_t *pe_i = &pe[i];
if (pe_i->portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, (void *)((long) eq))) {
uwsgi_error("port_associate");
}
}
}
return nget;
}
@@ -453,26 +209,22 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
ret = port_get(eq, &pe, NULL);
}
if (ret < 0) {
if (errno == ETIME) return 0;
if (errno != EINTR) {
if (errno != ETIME) {
uwsgi_error("port_get()");
return -1;
}
return -1;
return 0;
}
if (pe.portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, (void *)((long) eq))) {
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
uwsgi_error("port_associate");
}
}
#ifdef PORT_SOURCE_FILE
if (pe.portev_source == PORT_SOURCE_FILE || pe.portev_source == PORT_SOURCE_TIMER) {
#else
if (pe.portev_source == PORT_SOURCE_TIMER) {
#endif
*interesting_fd = (long) pe.portev_user;
}
else {
@@ -980,7 +732,6 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_PORT
#ifdef PORT_SOURCE_FILE
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
struct file_obj fo;
@@ -1041,14 +792,6 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
}
#else
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
return -1;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#endif
#endif
-499
View File
@@ -1,499 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
Exceptions management
generally exceptions are printed in the logs, but if you enable
an exception manager they will be stored in a (relatively big) uwsgi packet
with the following structure.
"vars" -> keyval of request vars
"backtrace" -> list of backtrace lines. Each line is a list of 5 elements filename,line,function,text,custom
"unix" -> seconds since the epoch
"class" -> the exception class
"msg" -> a text message mapped to the extension
"repr" -> a text message mapped to the extension in language-specific gergo
"wid" -> worker id
"core" -> the core generating the exception
"pid" -> pid of the worker
"node" -> hostname
Other vars can be added, but you cannot be sure they will be used by exceptions handler.
The exception-uwsgi packet is passed "as is" to the exception handler
Exceptions hooks:
a request plugin can export that hooks:
struct uwsgi_buffer *backtrace(struct wsgi_request *);
struct uwsgi_buffer *exception_class(struct wsgi_request *);
struct uwsgi_buffer *exception_msg(struct wsgi_request *);
struct uwsgi_buffer *exception_repr(struct wsgi_request *);
void exception_log(struct wsgi_request *);
Remember to reset the exception status (if possibile) after each call
Exceptions catcher:
This is a special development-mode in which exceptions are printed
to the HTTP client.
*/
struct uwsgi_buffer *uwsgi_exception_handler_object(struct wsgi_request *wsgi_req) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
if (uwsgi_buffer_append_keyval(ub, "vars", 4, wsgi_req->buffer,wsgi_req->uh->pktsize)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->backtrace) {
struct uwsgi_buffer *bt = uwsgi.p[wsgi_req->uh->modifier1]->backtrace(wsgi_req);
if (bt) {
if (uwsgi_buffer_append_keyval(ub, "backtrace", 9, bt->buf, bt->pos)) {
uwsgi_buffer_destroy(bt);
goto error;
}
uwsgi_buffer_destroy(bt);
}
}
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
struct uwsgi_buffer *ec = uwsgi.p[wsgi_req->uh->modifier1]->exception_class(wsgi_req);
if (ec) {
if (uwsgi_buffer_append_keyval(ub, "class", 5, ec->buf, ec->pos)) {
uwsgi_buffer_destroy(ec);
goto error;
}
uwsgi_buffer_destroy(ec);
}
}
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
struct uwsgi_buffer *em = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (em) {
if (uwsgi_buffer_append_keyval(ub, "msg", 3, em->buf, em->pos)) {
uwsgi_buffer_destroy(em);
goto error;
}
uwsgi_buffer_destroy(em);
}
}
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
struct uwsgi_buffer *er = uwsgi.p[wsgi_req->uh->modifier1]->exception_repr(wsgi_req);
if (er) {
if (uwsgi_buffer_append_keyval(ub, "repr", 4, er->buf, er->pos)) {
uwsgi_buffer_destroy(er);
goto error;
}
uwsgi_buffer_destroy(er);
}
}
if (uwsgi_buffer_append_keynum(ub, "unix", 4, uwsgi_now())) goto error;
if (uwsgi_buffer_append_keynum(ub, "wid", 3, uwsgi.mywid)) goto error;
if (uwsgi_buffer_append_keynum(ub, "pid", 3, uwsgi.mypid)) goto error;
if (uwsgi_buffer_append_keynum(ub, "core", 4, wsgi_req->async_id)) goto error;
if (uwsgi_buffer_append_keyval(ub, "node", 4, uwsgi.hostname, uwsgi.hostname_len)) goto error;
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
static void append_vars_to_ubuf(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
struct uwsgi_buffer *ub = (struct uwsgi_buffer *) data;
if (uwsgi_buffer_append(ub, key, keylen)) return;
if (uwsgi_buffer_append(ub, " = ", 3)) return;
if (uwsgi_buffer_append(ub, val, vallen)) return;
if (uwsgi_buffer_append(ub, "\n", 1)) return;
}
static void append_backtrace_to_ubuf(uint16_t pos, char *value, uint16_t len, void *data) {
struct uwsgi_buffer *ub = (struct uwsgi_buffer *) data;
uint16_t item = 0;
if (pos > 0) {
item = pos % 5;
}
switch(item) {
// filename
case 0:
if (uwsgi_buffer_append(ub, "filename: \"", 11)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
break;
// lineno
case 1:
if (uwsgi_buffer_append(ub, "line: ", 6)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, " ", 1)) return;
break;
// function
case 2:
if (uwsgi_buffer_append(ub, "function: \"", 11)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
break;
// text
case 3:
if (len > 0) {
if (uwsgi_buffer_append(ub, "text/code: \"", 12)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
}
break;
// custom
case 4:
if (len > 0) {
if (uwsgi_buffer_append(ub, "custom: \"", 9)) return;
if (uwsgi_buffer_append(ub, value, len)) return;
if (uwsgi_buffer_append(ub, "\" ", 2)) return;
}
if (uwsgi_buffer_append(ub, "\n", 1)) return;
break;
default:
break;
}
}
int uwsgi_exceptions_catch(struct wsgi_request *wsgi_req) {
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) {
return -1;
}
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) {
return -1;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
if (uwsgi_buffer_append(ub, "uWSGI exceptions catcher for \"", 30)) goto error;
if (uwsgi_buffer_append(ub, wsgi_req->method, wsgi_req->method_len)) goto error;
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
if (uwsgi_buffer_append(ub, wsgi_req->uri, wsgi_req->uri_len)) goto error;
if (uwsgi_buffer_append(ub, "\" (request plugin: \"", 20)) goto error;
if (uwsgi_buffer_append(ub, (char *) uwsgi.p[wsgi_req->uh->modifier1]->name, strlen(uwsgi.p[wsgi_req->uh->modifier1]->name))) goto error;
if (uwsgi_buffer_append(ub, "\", modifier1: ", 14 )) goto error;
if (uwsgi_buffer_num64(ub, wsgi_req->uh->modifier1)) goto error;
if (uwsgi_buffer_append(ub, ")\n\n", 3)) goto error;
if (uwsgi_buffer_append(ub, "Exception: ", 11)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
struct uwsgi_buffer *ub_exc_repr = uwsgi.p[wsgi_req->uh->modifier1]->exception_repr(wsgi_req);
if (ub_exc_repr) {
if (uwsgi_buffer_append(ub, ub_exc_repr->buf, ub_exc_repr->pos)) {
uwsgi_buffer_destroy(ub_exc_repr);
goto error;
}
uwsgi_buffer_destroy(ub_exc_repr);
}
else {
goto notavail3;
}
}
else {
notavail3:
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
}
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
if (uwsgi_buffer_append(ub, "Exception class: ", 17)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
struct uwsgi_buffer *ub_exc_class = uwsgi.p[wsgi_req->uh->modifier1]->exception_class(wsgi_req);
if (ub_exc_class) {
if (uwsgi_buffer_append(ub, ub_exc_class->buf, ub_exc_class->pos)) {
uwsgi_buffer_destroy(ub_exc_class);
goto error;
}
uwsgi_buffer_destroy(ub_exc_class);
}
else {
goto notavail;
}
}
else {
notavail:
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
}
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
if (uwsgi_buffer_append(ub, "Exception message: ", 19)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
struct uwsgi_buffer *ub_exc_msg = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (ub_exc_msg) {
if (uwsgi_buffer_append(ub, ub_exc_msg->buf, ub_exc_msg->pos)) {
uwsgi_buffer_destroy(ub_exc_msg);
goto error;
}
uwsgi_buffer_destroy(ub_exc_msg);
}
else {
goto notavail2;
}
}
else {
notavail2:
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
}
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
if (uwsgi_buffer_append(ub, "Backtrace:\n", 11)) goto error;
if (uwsgi.p[wsgi_req->uh->modifier1]->backtrace) {
struct uwsgi_buffer *ub_exc_bt = uwsgi.p[wsgi_req->uh->modifier1]->backtrace(wsgi_req);
if (ub_exc_bt) {
struct uwsgi_buffer *parsed_bt = uwsgi_buffer_new(4096);
if (uwsgi_hooked_parse_array(ub_exc_bt->buf, ub_exc_bt->pos, append_backtrace_to_ubuf, parsed_bt)) {
uwsgi_buffer_destroy(ub_exc_bt);
uwsgi_buffer_destroy(parsed_bt);
goto error;
}
uwsgi_buffer_destroy(ub_exc_bt);
if (uwsgi_buffer_append(ub, parsed_bt->buf, parsed_bt->pos)) {
uwsgi_buffer_destroy(parsed_bt);
goto error;
}
uwsgi_buffer_destroy(parsed_bt);
}
else {
goto notavail4;
}
}
else {
notavail4:
if (uwsgi_buffer_append(ub, "-Not available-", 15)) goto error;
}
if (uwsgi_buffer_append(ub, "\n\n", 2)) goto error;
if (uwsgi_hooked_parse(wsgi_req->buffer, wsgi_req->uh->pktsize, append_vars_to_ubuf, ub)) {
goto error;
}
if (uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos)) {
goto error;
}
uwsgi_buffer_destroy(ub);
return 0;
error:
uwsgi_buffer_destroy(ub);
return -1;
}
static void uwsgi_exception_run_handlers(struct uwsgi_buffer *ub) {
struct uwsgi_string_list *usl = uwsgi.exception_handlers_instance;
struct iovec iov[2];
iov[1].iov_base = ub->buf;
iov[1].iov_len = ub->pos;
while(usl) {
struct uwsgi_exception_handler_instance *uehi = (struct uwsgi_exception_handler_instance *) usl->custom_ptr;
iov[0].iov_base = &uehi;
iov[0].iov_len = sizeof(long);
// now send the message to the exception handler thread
if (writev(uwsgi.exception_handler_thread->pipe[0], iov, 2) != (ssize_t) (ub->pos+sizeof(long))) {
uwsgi_error("[uwsgi-exception-handler-error] uwsgi_exception_run_handlers()/writev()");
}
usl = usl->next;
}
}
void uwsgi_manage_exception(struct wsgi_request *wsgi_req,int catch) {
int do_exit = uwsgi.reload_on_exception;
if (!wsgi_req) goto log2;
if (do_exit) goto check_catch;
if (uwsgi.exception_handlers_instance) {
struct uwsgi_buffer *ehi = uwsgi_exception_handler_object(wsgi_req);
if (ehi) {
uwsgi_exception_run_handlers(ehi);
uwsgi_buffer_destroy(ehi);
}
}
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].exceptions++;
uwsgi_apps[wsgi_req->app_id].exceptions++;
if (uwsgi.reload_on_exception_type && uwsgi.p[wsgi_req->uh->modifier1]->exception_class) {
struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (ub) {
struct uwsgi_string_list *usl = uwsgi.reload_on_exception_type;
while (usl) {
if (!uwsgi_strncmp(usl->value, usl->len, ub->buf, ub->len)) {
do_exit = 1;
uwsgi_buffer_destroy(ub);
goto check_catch;
}
usl = usl->next;
}
uwsgi_buffer_destroy(ub);
}
}
if (uwsgi.reload_on_exception_value && uwsgi.p[wsgi_req->uh->modifier1]->exception_msg) {
struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (ub) {
struct uwsgi_string_list *usl = uwsgi.reload_on_exception_value;
while (usl) {
if (!uwsgi_strncmp(usl->value, usl->len, ub->buf, ub->len)) {
do_exit = 1;
uwsgi_buffer_destroy(ub);
goto check_catch;
}
usl = usl->next;
}
uwsgi_buffer_destroy(ub);
}
}
if (uwsgi.reload_on_exception_repr && uwsgi.p[wsgi_req->uh->modifier1]->exception_repr) {
struct uwsgi_buffer *ub = uwsgi.p[wsgi_req->uh->modifier1]->exception_msg(wsgi_req);
if (ub) {
struct uwsgi_string_list *usl = uwsgi.reload_on_exception_repr;
while (usl) {
if (!uwsgi_strncmp(usl->value, usl->len, ub->buf, ub->len)) {
do_exit = 1;
uwsgi_buffer_destroy(ub);
goto check_catch;
}
usl = usl->next;
}
uwsgi_buffer_destroy(ub);
}
}
check_catch:
if (catch && wsgi_req) {
if (uwsgi_exceptions_catch(wsgi_req)) {
// for now, just goto, new features could be added
goto log;
}
}
log:
if (uwsgi.p[wsgi_req->uh->modifier1]->exception_log) {
uwsgi.p[wsgi_req->uh->modifier1]->exception_log(wsgi_req);
}
log2:
if (do_exit) {
exit(UWSGI_EXCEPTION_CODE);
}
}
struct uwsgi_exception_handler *uwsgi_register_exception_handler(char *name, int (*func)(struct uwsgi_exception_handler_instance *, char *, size_t)) {
struct uwsgi_exception_handler *old_ueh = NULL, *ueh = uwsgi.exception_handlers;
while(ueh) {
if (!strcmp(name, ueh->name)) {
return NULL;
}
old_ueh = ueh;
ueh = ueh->next;
}
ueh = uwsgi_calloc(sizeof(struct uwsgi_exception_handler));
ueh->name = name;
ueh->func = func;
if (old_ueh) {
old_ueh->next = ueh;
}
else {
uwsgi.exception_handlers = ueh;
}
return ueh;
}
struct uwsgi_exception_handler *uwsgi_exception_handler_by_name(char *name) {
struct uwsgi_exception_handler *ueh = uwsgi.exception_handlers;
while(ueh) {
if (!strcmp(name, ueh->name)) {
return ueh;
}
ueh = ueh->next;
}
return NULL;
}
static void uwsgi_exception_handler_thread_loop(struct uwsgi_thread *ut) {
char *buf = uwsgi_malloc(uwsgi.exception_handler_msg_size + sizeof(long));
for (;;) {
int interesting_fd = -1;
int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
if (ret > 0) {
ssize_t len = read(ut->pipe[1], buf, uwsgi.exception_handler_msg_size + sizeof(long));
if (len > (ssize_t)(sizeof(long) + 1)) {
size_t msg_size = len - sizeof(long);
char *msg = buf + sizeof(long);
long ptr = 0;
memcpy(&ptr, buf, sizeof(long));
struct uwsgi_exception_handler_instance *uehi = (struct uwsgi_exception_handler_instance *) ptr;
if (!uehi)
break;
if (uehi->handler->func(uehi, msg, msg_size)) {
uwsgi_log("[uwsgi-exception] error running the handler \"%s\" args: \"%s\"\n", uehi->handler->name, uehi->arg ? uehi->arg : "");
}
}
}
}
free(buf);
}
void uwsgi_exception_setup_handlers() {
struct uwsgi_string_list *usl = uwsgi.exception_handlers_instance;
while(usl) {
char *handler = uwsgi_str(usl->value);
char *colon = strchr(handler, ':');
if (colon) {
*colon = 0;
}
struct uwsgi_exception_handler *ueh = uwsgi_exception_handler_by_name(handler);
if (!ueh) {
uwsgi_log("unable to find exception handler: %s\n", handler);
free(handler);
exit(1);
}
free(handler);
struct uwsgi_exception_handler_instance *uehi = uwsgi_calloc(sizeof(struct uwsgi_exception_handler_instance));
uehi->handler = ueh;
if (colon) {
uehi->arg = colon+1;
}
usl->custom_ptr = uehi;
usl = usl->next;
}
}
void uwsgi_exceptions_handler_thread_start() {
if (!uwsgi.exception_handlers_instance) return;
// start the exception_handler_thread
uwsgi.exception_handler_thread = uwsgi_thread_new(uwsgi_exception_handler_thread_loop);
if (!uwsgi.exception_handler_thread) {
uwsgi_log("unable to spawn exception handler thread\n");
exit(1);
}
}
-122
View File
@@ -1,122 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
the --master-fifo option create a unix named pipe (fifo) you can use to send management
commands to the master:
echo r > myfifo
*/
// this var can be accessed by plugins and hooks
void (*uwsgi_fifo_table[256])(int);
static char *uwsgi_fifo_by_slot() {
int count = 0;
struct uwsgi_string_list *usl;
uwsgi_foreach(usl, uwsgi.master_fifo) {
if (count == uwsgi.master_fifo_slot) return usl->value;
count++;
}
return uwsgi.master_fifo->value;
}
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; }
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; }
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; }
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; }
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; }
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; }
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; }
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; }
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; }
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; }
/*
this is called as soon as possibile allowing plugins (or hooks) to override it
*/
void uwsgi_master_fifo_prepare() {
int i;
for(i=0;i<256;i++) {
uwsgi_fifo_table[i] = NULL;
}
uwsgi_fifo_table['0'] = uwsgi_fifo_set_slot_zero;
uwsgi_fifo_table['1'] = uwsgi_fifo_set_slot_one;
uwsgi_fifo_table['2'] = uwsgi_fifo_set_slot_two;
uwsgi_fifo_table['3'] = uwsgi_fifo_set_slot_three;
uwsgi_fifo_table['4'] = uwsgi_fifo_set_slot_four;
uwsgi_fifo_table['5'] = uwsgi_fifo_set_slot_five;
uwsgi_fifo_table['6'] = uwsgi_fifo_set_slot_six;
uwsgi_fifo_table['7'] = uwsgi_fifo_set_slot_seven;
uwsgi_fifo_table['8'] = uwsgi_fifo_set_slot_eight;
uwsgi_fifo_table['9'] = uwsgi_fifo_set_slot_nine;
uwsgi_fifo_table['-'] = uwsgi_cheaper_decrease;
uwsgi_fifo_table['+'] = uwsgi_cheaper_increase;
uwsgi_fifo_table['c'] = uwsgi_chain_reload;
uwsgi_fifo_table['C'] = uwsgi_go_cheap;
uwsgi_fifo_table['f'] = uwsgi_refork_master;
uwsgi_fifo_table['l'] = uwsgi_log_reopen;
uwsgi_fifo_table['L'] = uwsgi_log_rotate;
uwsgi_fifo_table['p'] = suspend_resume_them_all;
uwsgi_fifo_table['P'] = uwsgi_update_pidfiles;
uwsgi_fifo_table['q'] = gracefully_kill_them_all;
uwsgi_fifo_table['Q'] = kill_them_all;
uwsgi_fifo_table['r'] = grace_them_all;
uwsgi_fifo_table['R'] = reap_them_all;
uwsgi_fifo_table['s'] = stats;
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
}
int uwsgi_master_fifo() {
char *path = uwsgi_fifo_by_slot();
unlink(path);
if (mkfifo(path, S_IRUSR|S_IWUSR)) {
uwsgi_error("uwsgi_master_fifo()/mkfifo()");
exit(1);
}
int fd = open(path, O_RDONLY|O_NONBLOCK);
if (fd < 0) {
uwsgi_error("uwsgi_master_fifo()/open()");
exit(1);
}
uwsgi_socket_nb(fd);
return fd;
}
int uwsgi_master_fifo_manage(int fd) {
char cmd;
ssize_t rlen = read(fd, &cmd, 1);
if (rlen < 0) {
if (uwsgi_is_again()) return 0;
uwsgi_error("uwsgi_master_fifo_manage()/read()");
exit(1);
}
// fifo destroyed, recreate it
else if (rlen == 0) {
close(fd);
uwsgi.master_fifo_fd = uwsgi_master_fifo();
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.master_fifo_fd);
return 0;
}
if (uwsgi_fifo_table[(int) cmd]) {
uwsgi_fifo_table[(int) cmd](0);
}
return 0;
}
-213
View File
@@ -1,213 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
#include <sys/inotify.h>
#endif
#endif
void uwsgi_fsmon_setup() {
struct uwsgi_string_list *usl = uwsgi.fs_reload;
while(usl) {
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
char *copy = uwsgi_str(usl->value);
char *space = strchr(copy, ' ');
if (!space) {
uwsgi_log("[uwsgi-fsmon] invalid syntax: \"%s\"\n", usl->value);
goto next;
}
*space = 0;
usl->value = copy;
usl->len = strlen(copy);
usl->custom_ptr = space+1;
if (uwsgi_register_fsmon(usl)) {
uwsgi_log("[uwsgi-fsmon] unable to register monitor for \"%s\"\n", usl->value);
}
else {
uwsgi_log("[uwsgi-fsmon] registered monitor for \"%s\"\n", usl->value);
}
next:
usl = usl->next;
}
}
int uwsgi_register_fsmon(struct uwsgi_string_list *usl) {
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
static int inotify_fd = -1;
if (inotify_fd == -1) {
inotify_fd = inotify_init();
if (inotify_fd < 0) {
uwsgi_error("uwsgi_register_fsmon()/inotify_init()");
return -1;
}
if (event_queue_add_fd_read(uwsgi.master_queue, inotify_fd)) {
uwsgi_error("uwsgi_register_fsmon()/event_queue_add_fd_read()");
return -1;
}
}
int wd = inotify_add_watch(inotify_fd, usl->value, IN_ATTRIB | IN_CREATE | IN_DELETE | IN_DELETE_SELF | IN_MODIFY | IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO);
if (wd < 0) {
uwsgi_error("uwsgi_register_fsmon()/inotify_add_watch()");
return -1;
}
usl->custom = inotify_fd;
usl->custom2 = wd;
return 0;
#endif
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_KQUEUE
struct kevent kev;
int fd = open(usl->value, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(usl->value);
uwsgi_error("uwsgi_register_fsmon()/open()");
return -1;
}
EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD | EV_CLEAR, NOTE_WRITE | NOTE_DELETE | NOTE_EXTEND | NOTE_ATTRIB | NOTE_RENAME | NOTE_REVOKE, 0, 0);
if (kevent(uwsgi.master_queue, &kev, 1, NULL, 0, NULL) < 0) {
uwsgi_error("uwsgi_register_fsmon()/kevent()");
return -1;
}
usl->custom = fd;
usl->custom2 = fd;
return 0;
#endif
uwsgi_log("[uwsgi-fsmon] filesystem monitoring interface not available in this platform !!!\n");
return 1;
}
static struct uwsgi_string_list *uwsgi_fsmon_ack(int interesting_fd) {
int found_fd = -1;
struct uwsgi_string_list *usl = uwsgi.fs_reload;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
if ((int)usl->custom == interesting_fd) {
found_fd = usl->custom;
goto found;
}
usl = usl->next;
}
found:
if (found_fd == -1) return NULL;
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifndef OBSOLETE_LINUX_KERNEL
unsigned int isize = 0;
if (ioctl(found_fd, FIONREAD, &isize) < 0) {
uwsgi_error("uwsgi_fsmon_ack()/ioctl()");
return 0;
}
if (isize == 0) return NULL;
struct inotify_event *ie = uwsgi_malloc(isize);
// read from the inotify descriptor
ssize_t len = read(found_fd, ie, isize);
if (len < 0) { free(ie); uwsgi_error("uwsgi_fsmon_ack()/read()"); return NULL;}
found_fd = ie->wd;
free(ie);
#endif
#endif
// search for the item id and print it
usl = uwsgi.fs_reload;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return uwsgi.fs_reload;
}
usl = usl->next;
}
usl = uwsgi.fs_brutal_reload;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return uwsgi.fs_brutal_reload;
}
usl = usl->next;
}
usl = uwsgi.fs_signal;
while(usl) {
if ((int)usl->custom2 == found_fd) {
uwsgi_log("[uwsgi-fsmon] \"%s\" has been modified\n", usl->value);
return usl;
}
usl = usl->next;
}
return NULL;
}
int uwsgi_fsmon_event(int interesting_fd) {
struct uwsgi_string_list *usl = uwsgi_fsmon_ack(interesting_fd);
if (!usl) return 0;
if (usl == uwsgi.fs_reload) {
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
return 1;
}
if (usl == uwsgi.fs_brutal_reload) {
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
return 1;
}
// fallback to signal
uwsgi_route_signal(atoi(usl->custom_ptr));
return 1;
}
+4 -14
View File
@@ -18,9 +18,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
}
}
char *str = uwsgi_num2str(num);
char *fullname = uwsgi_concat3(name, " ", str);
free(str);
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
ug = &ushared->gateways[ushared->gateways_cnt];
ug->pid = 0;
@@ -30,18 +28,11 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
ug->fullname = fullname;
ug->data = data;
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, ug->internal_subscription_pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
#endif
uwsgi_error("socketpair()");
}
uwsgi_socket_nb(ug->internal_subscription_pipe[0]);
uwsgi_socket_nb(ug->internal_subscription_pipe[1]);
if (!uwsgi.master_process && !uwsgi.force_gateway)
if (!uwsgi.master_process)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
@@ -51,7 +42,7 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
}
static void gateway_brutal_end() {
_exit(UWSGI_END_CODE);
_exit(UWSGI_END_CODE);
}
void gateway_respawn(int id) {
@@ -70,7 +61,6 @@ 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__
@@ -92,7 +82,7 @@ void gateway_respawn(int id) {
ug->loop(id, ug->data);
// never here !!! (i hope)
exit(1);
_exit(1);
}
ug->pid = gw_pid;
-93
View File
@@ -1,93 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
// Bernstein classic hash (this is not static as it is used by other areas)
uint32_t djb33x_hash(char *key, uint64_t keylen) {
register uint32_t hash = 5381;
uint64_t i;
for (i = 0; i < keylen; i++) {
hash = ((hash << 5) + hash) ^ key[i];
}
return hash;
}
// Murmur2 hash Copyright (C) Austin Appleby
// adapted from nginx
uint32_t murmur2_hash(char *key, uint64_t keylen) {
uint32_t h, k;
uint8_t *ukey = (uint8_t *) key;
h = 0 ^ keylen;
while (keylen >= 4) {
k = ukey[0];
k |= ukey[1] << 8;
k |= ukey[2] << 16;
k |= ukey[3] << 24;
k *= 0x5bd1e995;
k ^= k >> 24;
k *= 0x5bd1e995;
h *= 0x5bd1e995;
h ^= k;
ukey += 4;
keylen -= 4;
}
switch (keylen) {
case 3:
h ^= key[2] << 16;
case 2:
h ^= key[1] << 8;
case 1:
h ^= key[0];
h *= 0x5bd1e995;
}
h ^= h >> 13;
h *= 0x5bd1e995;
h ^= h >> 15;
return h;
}
struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *name) {
struct uwsgi_hash_algo *uha = uwsgi.hash_algos;
while(uha) {
if (!strcmp(name, uha->name)) {
return uha;
}
uha = uha->next;
}
return NULL;
}
void uwsgi_hash_algo_register(char *name, uint32_t (*func)(char *, uint64_t)) {
struct uwsgi_hash_algo *old_uha = NULL, *uha = uwsgi.hash_algos;
while(uha) {
if (!strcmp(uha->name, name)) return;
old_uha = uha;
uha = uha->next;
}
uha = uwsgi_calloc(sizeof(struct uwsgi_hash_algo));
uha->name = name;
uha->func = func;
if (old_uha) {
old_uha->next = uha;
}
else {
uwsgi.hash_algos = uha;
}
}
void uwsgi_hash_algo_register_all() {
uwsgi_hash_algo_register("djb33x", djb33x_hash);
uwsgi_hash_algo_register("murmur2", murmur2_hash);
}
-217
View File
@@ -1,217 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
/*
advanced (pluggable) hooks
they are executed before the other hooks, and can be extended by plugins
if a plugin tries to register an hook with a name already available in the list, its function
will be overridden
*/
struct uwsgi_hook *uwsgi_hook_by_name(char *name) {
struct uwsgi_hook *uh = uwsgi.hooks;
while(uh) {
if (!strcmp(uh->name, name)) {
return uh;
}
uh = uh->next;
}
return NULL;
}
void uwsgi_register_hook(char *name, int (*func)(char *)) {
struct uwsgi_hook *old_uh = NULL, *uh = uwsgi.hooks;
while(uh) {
if (!strcmp(uh->name, name)) {
uh->func = func;
return;
}
old_uh = uh;
uh = uh->next;
}
uh = uwsgi_calloc(sizeof(struct uwsgi_hook));
uh->name = name;
uh->func = func;
if (old_uh) {
old_uh->next = uh;
}
else {
uwsgi.hooks = uh;
}
}
static int uwsgi_hook_chdir(char *arg) {
int ret = chdir(arg);
if (ret) {
uwsgi_error("uwsgi_hook_chdir()");
}
return ret;
}
static int uwsgi_hook_exec(char *arg) {
int ret = uwsgi_run_command_and_wait(NULL, arg);
if (ret != 0) {
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", arg, ret);
}
return ret;
}
static int uwsgi_hook_exit(char *arg) {
int exit_code = 0;
if (strlen(arg) > 1) {
exit_code = atoi(arg);
}
exit(exit_code);
}
static int uwsgi_hook_print(char *arg) {
char *line = uwsgi_concat2(arg, "\n");
uwsgi_log(line);
free(line);
return 0;
}
static int uwsgi_hook_callint(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
*space = 0;
int num = atoi(space+1);
void (*func)(int) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
*space = ' ';
return -1;
}
*space = ' ';
func(num);
}
else {
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", arg);
return -1;
}
func();
}
return 0;
}
static int uwsgi_hook_call(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
*space = 0;
void (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
*space = ' ';
return -1;
}
*space = ' ';
func(space + 1);
}
else {
void (*func)(void) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", arg);
return -1;
}
func();
}
return 0;
}
static int uwsgi_hook_callintret(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
*space = 0;
int num = atoi(space+1);
int (*func)(int) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s(%d)\"\n", arg, num);
*space = ' ';
return -1;
}
*space = ' ';
return func(num);
}
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", arg);
return -1;
}
return func();
}
static int uwsgi_hook_callret(char *arg) {
char *space = strchr(arg, ' ');
if (space) {
*space = 0;
int (*func)(char *) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s(%s)\"\n", arg, space + 1);
*space = ' ';
return -1;
}
*space = ' ';
return func(space + 1);
}
int (*func)(void) = dlsym(RTLD_DEFAULT, arg);
if (!func) {
uwsgi_log("unable to call function \"%s\"\n", arg);
return -1;
}
return func();
}
void uwsgi_register_base_hooks() {
uwsgi_register_hook("cd", uwsgi_hook_chdir);
uwsgi_register_hook("exec", uwsgi_hook_exec);
uwsgi_register_hook("mount", uwsgi_mount_hook);
uwsgi_register_hook("umount", uwsgi_umount_hook);
uwsgi_register_hook("call", uwsgi_hook_call);
uwsgi_register_hook("callret", uwsgi_hook_callret);
uwsgi_register_hook("callint", uwsgi_hook_callint);
uwsgi_register_hook("callintret", uwsgi_hook_callintret);
// for testing
uwsgi_register_hook("exit", uwsgi_hook_exit);
uwsgi_register_hook("print", uwsgi_hook_print);
}
void uwsgi_hooks_run(struct uwsgi_string_list *l, char *phase, int fatal) {
struct uwsgi_string_list *usl = NULL;
uwsgi_foreach(usl, l) {
char *colon = strchr(usl->value, ':');
if (!colon) {
uwsgi_log("invalid hook syntax, must be hook:args\n");
exit(1);
}
*colon = 0;
struct uwsgi_hook *uh = uwsgi_hook_by_name(usl->value);
if (!uh) {
uwsgi_log("hook not found: %s\n", usl->value);
exit(1);
}
*colon = ':';
uwsgi_log("running \"%s\" (%s)...\n", usl->value, phase);
int ret = uh->func(colon+1);
if (fatal && ret != 0) {
exit(1);
}
}
}
+10 -24
View File
@@ -1,4 +1,6 @@
#include <uwsgi.h>
#ifdef UWSGI_INI
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
@@ -7,8 +9,6 @@ extern struct uwsgi_server uwsgi;
This memory must not be freed for all the server lifecycle
*/
static char *last_file = NULL;
void ini_rstrip(char *line) {
off_t i;
@@ -54,9 +54,9 @@ char *ini_get_key(char *key) {
return ptr;
}
char *ini_get_line(char *ini, size_t size) {
char *ini_get_line(char *ini, off_t size) {
size_t i;
off_t i;
char *ptr = ini;
for (i = 0; i < size; i++) {
@@ -78,7 +78,7 @@ char *ini_get_line(char *ini, size_t size) {
void uwsgi_ini_config(char *file, char *magic_table[]) {
size_t len = 0;
int len = 0;
char *ini;
char *ini_line;
@@ -91,7 +91,6 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
char *section_asked = "uwsgi";
char *colon;
int got_section = 0;
if (uwsgi_check_scheme(file)) {
@@ -107,23 +106,13 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
if (colon[1] != 0) {
section_asked = colon + 1;
}
if (colon == file) {
file = last_file;
}
}
if (file[0] != 0 && file != last_file) {
uwsgi_log_initial("[uWSGI] getting INI configuration from %s\n", file);
if (file[0] != 0) {
uwsgi_log("[uWSGI] getting INI configuration from %s\n", file);
}
ini = uwsgi_open_and_read(file, &len, 1, magic_table);
if (file != last_file) {
if (last_file) {
free(last_file);
}
last_file = uwsgi_str(file);
}
while (len) {
ini_line = ini_get_line(ini, len);
@@ -148,7 +137,6 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
val = ini_get_key(key);
if (!strcmp(section, section_asked)) {
got_section = 1;
ini_rstrip(key);
val = ini_lstrip(val);
ini_rstrip(val);
@@ -163,13 +151,11 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
}
if (!got_section) {
uwsgi_log("*** WARNING: Can't find section \"%s\" in INI configuration file %s ***\n", section_asked, file);
}
if (colon) {
colon[0] = ':';
}
}
#endif
+19 -215
View File
@@ -2,61 +2,6 @@
extern struct uwsgi_server uwsgi;
struct http_status_codes {
const char key[3];
const char *message;
int message_size;
};
/* statistically ordered */
struct http_status_codes hsc[] = {
{"200", "OK"},
{"302", "Found"},
{"404", "Not Found"},
{"500", "Internal Server Error"},
{"301", "Moved Permanently"},
{"304", "Not Modified"},
{"303", "See Other"},
{"403", "Forbidden"},
{"307", "Temporary Redirect"},
{"401", "Unauthorized"},
{"400", "Bad Request"},
{"405", "Method Not Allowed"},
{"408", "Request Timeout"},
{"100", "Continue"},
{"101", "Switching Protocols"},
{"201", "Created"},
{"202", "Accepted"},
{"203", "Non-Authoritative Information"},
{"204", "No Content"},
{"205", "Reset Content"},
{"206", "Partial Content"},
{"300", "Multiple Choices"},
{"305", "Use Proxy"},
{"402", "Payment Required"},
{"406", "Not Acceptable"},
{"407", "Proxy Authentication Required"},
{"409", "Conflict"},
{"410", "Gone"},
{"411", "Length Required"},
{"412", "Precondition Failed"},
{"413", "Request Entity Too Large"},
{"414", "Request-URI Too Long"},
{"415", "Unsupported Media Type"},
{"416", "Requested Range Not Satisfiable"},
{"417", "Expectation Failed"},
{"501", "Not Implemented"},
{"502", "Bad Gateway"},
{"503", "Service Unavailable"},
{"504", "Gateway Timeout"},
{"505", "HTTP Version Not Supported"},
{"", NULL},
};
void uwsgi_init_default() {
uwsgi.cpus = 1;
@@ -68,6 +13,7 @@ void uwsgi_init_default() {
uwsgi.signal_socket = -1;
uwsgi.my_signal_socket = -1;
uwsgi.cache_server_fd = -1;
uwsgi.stats_fd = -1;
uwsgi.stats_pusher_default_freq = 3;
@@ -75,12 +21,10 @@ 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;
@@ -88,18 +32,15 @@ void uwsgi_init_default() {
uwsgi.subscribe_freq = 10;
uwsgi.subscription_tolerance = 17;
uwsgi.cluster_fd = -1;
uwsgi.cores = 1;
uwsgi.threads = 1;
// default max number of rpc slot
uwsgi.rpc_max = 64;
uwsgi.offload_threads_events = 64;
uwsgi.default_app = -1;
uwsgi.buffer_size = 4096;
uwsgi.body_read_warning = 8;
uwsgi.numproc = 1;
uwsgi.forkbomb_delay = 2;
@@ -111,22 +52,18 @@ void uwsgi_init_default() {
uwsgi.log_master_bufsize = 8192;
uwsgi.worker_reload_mercy = 60;
uwsgi.max_vars = MAX_VARS;
uwsgi.vec_size = 4 + 1 + (4 * MAX_VARS);
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = 4;
uwsgi.shared->options[UWSGI_OPTION_LOGGING] = 1;
// a workers hould be running for at least 10 seconds
uwsgi.shared->options[UWSGI_OPTION_MIN_WORKER_LIFETIME] = 10;
#ifdef UWSGI_SPOOLER
uwsgi.shared->spooler_frequency = 30;
uwsgi.shared->spooler_signal_pipe[0] = -1;
uwsgi.shared->spooler_signal_pipe[1] = -1;
#endif
uwsgi.shared->mule_signal_pipe[0] = -1;
uwsgi.shared->mule_signal_pipe[1] = -1;
@@ -136,50 +73,20 @@ void uwsgi_init_default() {
uwsgi.shared->worker_log_pipe[0] = -1;
uwsgi.shared->worker_log_pipe[1] = -1;
uwsgi.shared->worker_req_log_pipe[0] = -1;
uwsgi.shared->worker_req_log_pipe[1] = -1;
uwsgi.req_log_fd = 2;
#ifdef UWSGI_SSL
// 1 day of tolerance
uwsgi.subscriptions_sign_check_tolerance = 3600 * 24;
uwsgi.ssl_sessions_timeout = 300;
#endif
#ifdef UWSGI_ALARM
uwsgi.alarm_freq = 3;
uwsgi.alarm_msg_size = 8192;
uwsgi.exception_handler_msg_size = 65536;
uwsgi.multicast_ttl = 1;
uwsgi.multicast_loop = 1;
// filling http status codes
struct http_status_codes *http_sc;
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = strlen(http_sc->message);
}
uwsgi.empty = "";
#ifdef __linux__
uwsgi.cgroup_dir_mode = "0700";
#endif
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
uwsgi_websockets_init();
// 1 MB default limit
uwsgi.chunked_input_limit = 1024*1024;
#ifdef UWSGI_MULTICAST
uwsgi.multicast_ttl = 1;
#endif
// clear reforked status
uwsgi.master_is_reforked = 0;
uwsgi.master_fifo_fd = -1;
uwsgi_master_fifo_prepare();
}
void uwsgi_setup_reload() {
@@ -224,19 +131,21 @@ void uwsgi_autoload_plugins_by_name(char *argv_zero) {
p = original_proc_name;
p = strstr(p, "uwsgi_");
if (p != NULL) {
char *ctx = NULL;
uwsgi_foreach_token(uwsgi_str(p + 6), "_", plugins_requested, ctx) {
plugins_requested = strtok(uwsgi_str(p + 6), "_");
while (plugins_requested) {
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
uwsgi_load_plugin(-1, plugins_requested, NULL);
plugins_requested = strtok(NULL, "_");
}
}
plugins_requested = getenv("UWSGI_PLUGINS");
if (plugins_requested) {
plugins_requested = uwsgi_concat2(plugins_requested, "");
char *p, *ctx = NULL;
uwsgi_foreach_token(plugins_requested, ",", p, ctx) {
char *p = strtok(plugins_requested, ",");
while (p != NULL) {
uwsgi_load_plugin(-1, p, NULL);
p = strtok(NULL, ",");
}
}
@@ -309,7 +218,7 @@ void uwsgi_commandline_config() {
void uwsgi_setup_workers() {
int i, j;
// allocate shared memory for workers + master
uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1));
uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1 + uwsgi.grunt));
for (i = 0; i <= uwsgi.numproc; i++) {
// allocate memory for apps
@@ -320,8 +229,7 @@ void uwsgi_setup_workers() {
// this is a trick for avoiding too much memory areas
void *ts = uwsgi_calloc_shared(sizeof(void *) * uwsgi.max_apps * uwsgi.cores);
// add 4 bytes for uwsgi header
void *buffers = uwsgi_malloc_shared((uwsgi.buffer_size+4) * uwsgi.cores);
void *buffers = uwsgi_malloc_shared(uwsgi.buffer_size * uwsgi.cores);
void *hvec = uwsgi_malloc_shared(sizeof(struct iovec) * uwsgi.vec_size * uwsgi.cores);
void *post_buf = NULL;
if (uwsgi.post_buffering > 0)
@@ -331,8 +239,8 @@ void uwsgi_setup_workers() {
for (j = 0; j < uwsgi.cores; j++) {
// allocate shared memory for thread states (required for some language, like python)
uwsgi.workers[i].cores[j].ts = ts + ((sizeof(void *) * uwsgi.max_apps) * j);
// raw per-request buffer (+4 bytes for uwsgi header)
uwsgi.workers[i].cores[j].buffer = buffers + ((uwsgi.buffer_size+4) * j);
// raw per-request buffer
uwsgi.workers[i].cores[j].buffer = buffers + (uwsgi.buffer_size * j);
// iovec for uwsgi vars
uwsgi.workers[i].cores[j].hvec = hvec + ((sizeof(struct iovec) * uwsgi.vec_size) * j);
if (post_buf)
@@ -354,18 +262,7 @@ void uwsgi_setup_workers() {
}
total_memory *= (uwsgi.numproc + uwsgi.master_process);
if (uwsgi.numproc > 0)
uwsgi_log("mapped %llu bytes (%llu KB) for %d cores\n", (unsigned long long) total_memory, (unsigned long long) (total_memory / 1024), uwsgi.cores * uwsgi.numproc);
// allocate signal table
uwsgi.shared->signal_table = uwsgi_calloc_shared(sizeof(struct uwsgi_signal_entry) * 256 * (uwsgi.numproc + 1));
#ifdef UWSGI_ROUTING
uwsgi_fixup_routes(uwsgi.routes);
uwsgi_fixup_routes(uwsgi.error_routes);
uwsgi_fixup_routes(uwsgi.response_routes);
uwsgi_fixup_routes(uwsgi.final_routes);
#endif
uwsgi_log("mapped %llu bytes (%llu KB) for %d cores\n", total_memory, total_memory / 1024, uwsgi.cores * uwsgi.numproc);
}
@@ -394,98 +291,5 @@ pid_t uwsgi_daemonize2() {
uwsgi_write_pidfile(uwsgi.pidfile2);
}
if (uwsgi.log_master) uwsgi_setup_log_master();
return uwsgi.mypid;
}
// fix/check related options
void sanitize_args() {
if (uwsgi.async > 1) {
uwsgi.cores = uwsgi.async;
}
if (uwsgi.threads > 1) {
uwsgi.has_threads = 1;
uwsgi.cores = uwsgi.threads;
}
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
if (!uwsgi.post_buffering) {
uwsgi_log(" *** WARNING: you have enabled harakiri without post buffering. Slow upload could be rejected on post-unbuffered webservers *** \n");
}
}
if (uwsgi.write_errors_exception_only) {
uwsgi.ignore_sigpipe = 1;
uwsgi.ignore_write_errors = 1;
}
if (uwsgi.cheaper_count == 0) uwsgi.cheaper = 0;
if (uwsgi.cheaper_count > 0 && uwsgi.cheaper_count >= uwsgi.numproc) {
uwsgi_log("invalid cheaper value: must be lower than processes\n");
exit(1);
}
if (uwsgi.cheaper && uwsgi.cheaper_count) {
if (uwsgi.cheaper_initial) {
if (uwsgi.cheaper_initial < uwsgi.cheaper_count) {
uwsgi_log("warning: invalid cheaper-initial value (%d), must be equal or higher than cheaper (%d), using %d as initial number of workers\n",
uwsgi.cheaper_initial, uwsgi.cheaper_count, uwsgi.cheaper_count);
uwsgi.cheaper_initial = uwsgi.cheaper_count;
}
else if (uwsgi.cheaper_initial > uwsgi.numproc) {
uwsgi_log("warning: invalid cheaper-initial value (%d), must be lower or equal than worker count (%d), using %d as initial number of workers\n",
uwsgi.cheaper_initial, uwsgi.numproc, uwsgi.numproc);
uwsgi.cheaper_initial = uwsgi.numproc;
}
}
else {
uwsgi.cheaper_initial = uwsgi.cheaper_count;
}
}
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]);
exit(1);
}
if (uwsgi.cheaper_rss_limit_soft && uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] != 1 && uwsgi.force_get_memusage != 1) {
uwsgi_log("enabling cheaper-rss-limit-soft requires enabling also memory-report\n");
exit(1);
}
if (uwsgi.cheaper_rss_limit_hard && !uwsgi.cheaper_rss_limit_soft) {
uwsgi_log("enabling cheaper-rss-limit-hard requires setting also cheaper-rss-limit-soft\n");
exit(1);
}
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);
}
/* here we try to choose if thunder lock is a good thing */
#ifdef UNBIT
if (uwsgi.numproc > 1 && !uwsgi.map_socket) {
uwsgi.use_thunder_lock = 1;
}
#endif
}
const char *uwsgi_http_status_msg(char *status, uint16_t *len) {
struct http_status_codes *http_sc;
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (!strncmp(http_sc->key, status, 3)) {
*len = http_sc->message_size;
return http_sc->message;
}
}
return NULL;
}
-1212
View File
File diff suppressed because it is too large Load Diff
+2 -4
View File
@@ -13,7 +13,7 @@ extern struct uwsgi_server uwsgi;
void uwsgi_json_config(char *file, char *magic_table[]) {
size_t len = 0;
int len = 0;
char *json_data;
@@ -45,7 +45,7 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
}
}
uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);
uwsgi_log("[uWSGI] getting JSON configuration from %s\n", file);
json_data = uwsgi_open_and_read(file, &len, 1, magic_table);
@@ -106,8 +106,6 @@ void uwsgi_json_config(char *file, char *magic_table[]) {
config_iter = json_object_iter_next(config, config_iter);
}
if (colon) colon[0] = ':';
}
#endif
+370
View File
@@ -0,0 +1,370 @@
#ifdef UWSGI_LDAP
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#include <ldap.h>
#ifndef LDAP_OPT_SUCCESS
#define LDAP_OPT_SUCCESS LDAP_SUCCESS
#endif
#ifndef ldap_unbind_ext_s
#define ldap_unbind_ext_s ldap_unbind_ext
#endif
void ldap2uwsgi(char *ldapname, char *uwsginame) {
char *ptr = uwsginame;
int i;
for (i = 0; i < (int) strlen(ldapname); i++) {
if (isupper((int) ldapname[i])) {
*ptr++ = '-';
*ptr++ = tolower((int) ldapname[i]);
}
else {
*ptr++ = ldapname[i];
}
}
*ptr++ = 0;
}
int calc_ldap_name(char *name) {
int i;
int counter = 0;
for (i = 0; i < (int) strlen(name); i++) {
if (isupper((int) name[i])) {
counter++;
}
}
return strlen(name) + counter;
}
struct uwsgi_ldap_entry {
int num;
char names[1024];
int has_arg;
};
void uwsgi_name_to_ldap(char *src, char *dst) {
int i;
char *ptr = dst;
memset(dst, 0, 1024);
strcat(dst, " 'uWSGI");
ptr += 7;
for (i = 0; i < (int) strlen(src); i++) {
if (src[i] == '-') {
i++;
*ptr++ = toupper((int) src[i]);
}
else {
*ptr++ = src[i];
}
}
strcat(dst, "'");
}
struct uwsgi_ldap_entry *get_ldap_by_num(struct uwsgi_ldap_entry *root, int num, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for (i = 0; i < count; i++) {
ule = &root[i];
if (ule->num == num) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *name, int count) {
int i;
struct uwsgi_ldap_entry *ule;
for (i = 0; i < count; i++) {
ule = &root[i];
if (uwsgi_list_has_str(ule->names, name + 1)) {
return ule;
}
}
return NULL;
}
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
*count = 0;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry) * uwsgi_count_options(op));
while (op && op->name) {
uwsgi_name_to_ldap((char *) op->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry)
goto next;
entry = &ule[*count];
entry->num = *count;
strcpy(entry->names, ldap_name);
*count = *count + 1;
entry->has_arg = op->type;
next:
op++;
}
return ule;
}
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
int i;
int items;
uwsgi_log("\n");
uwsgi_log("dn: cn=uwsgi,cn=schema,cn=config\n");
uwsgi_log("objectClass: olcSchemaConfig\n");
uwsgi_log("cn: uwsgi\n");
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for (i = 0; i < items; i++) {
entry = &ule[i];
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("olcAttributeTypes: ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("olcObjectClasses: ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for (i = 0; i < items; i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGInull ))\n");
uwsgi_log("\n");
exit(0);
}
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
int i;
int items;
struct uwsgi_ldap_entry *entry, *ule = get_ldap_names(&items);
for (i = 0; i < items; i++) {
entry = &ule[i];
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.%d NAME (%s", entry->num, entry->names);
if (entry->has_arg) {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )\n");
}
else {
uwsgi_log(" ) SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
}
}
uwsgi_log("attributetype ( 1.3.6.1.4.1.35156.17.4.50000 NAME 'uWSGInull' SYNTAX 1.3.6.1.4.1.1466.115.121.1.7 )\n");
uwsgi_log("objectclass ( 1.3.6.1.4.1.35156.17.3.1 NAME 'uWSGIConfig' SUP top AUXILIARY DESC 'uWSGI configuration' MAY ( ");
for (i = 0; i < items; i++) {
entry = &ule[i];
char *list2 = uwsgi_concat2(entry->names + 1, "");
char *p = strtok(list2, " ");
while (p != NULL) {
uwsgi_log("%.*s $ ", strlen(p) - 2, p + 1);
p = strtok(NULL, " ");
}
free(list2);
}
uwsgi_log("uWSGInull ))\n");
exit(0);
}
void uwsgi_ldap_config(char *url) {
LDAP *ldp;
LDAPMessage *results, *entry;
BerElement *ber;
struct berval **bervalues;
char *attr;
char *uwsgi_attr;
char *url_slash;
int desired_version = LDAP_VERSION3;
int ret;
LDAPURLDesc *ldap_url;
if (!ldap_is_ldap_url(url)) {
uwsgi_log("invalid LDAP url.\n");
exit(1);
}
if (ldap_url_parse(url, &ldap_url) != LDAP_SUCCESS) {
uwsgi_log("unable to parse LDAP url.\n");
exit(1);
}
uwsgi_log("[uWSGI] getting LDAP configuration from %s\n", url);
url_slash = strchr(url, '/');
url_slash = strchr(url_slash + 1, '/');
url_slash = strchr(url_slash + 1, '/');
if (url_slash) {
url_slash[0] = 0;
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP URL: %s\n", url);
uwsgi_debug("LDAP BASE DN: %s\n", ldap_url->lud_dn);
#endif
#if LDAP_API_VERSION >= 3000
if ((ret = ldap_initialize(&ldp, url)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#else
if ((ldp = ldap_init(ldap_url->lud_host, ldap_url->lud_port)) == NULL) {
uwsgi_error("ldap_init()");
exit(1);
}
#endif
if ((ret = ldap_set_option(ldp, LDAP_OPT_PROTOCOL_VERSION, &desired_version)) != LDAP_OPT_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
if ((ret = ldap_search_ext_s(ldp, ldap_url->lud_dn, ldap_url->lud_scope, ldap_url->lud_filter, NULL, 0, NULL, NULL, NULL, 1, &results)) != LDAP_SUCCESS) {
uwsgi_log("LDAP: %s\n", ldap_err2string(ret));
exit(1);
}
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP connection initialized %p\n", ldp);
#endif
free(ldap_url);
if (ldap_count_entries(ldp, results) < 1) {
uwsgi_log("no LDAP entry found\n");
exit(1);
}
entry = ldap_first_entry(ldp, results);
int found = 0;
for (attr = ldap_first_attribute(ldp, entry, &ber); attr != NULL; attr = ldap_next_attribute(ldp, entry, ber)) {
if (!strncmp(attr, "uWSGI", 5)) {
found = 1;
uwsgi_attr = malloc(calc_ldap_name(attr) + 1);
if (!uwsgi_attr) {
uwsgi_error("malloc()");
exit(1);
}
ldap2uwsgi(attr + 5, uwsgi_attr);
#ifdef UWSGI_DEBUG
uwsgi_debug("LDAP attribute: %s = --%s\n", attr, uwsgi_attr);
#endif
bervalues = ldap_get_values_len(ldp, entry, attr);
if (bervalues) {
// do not free uwsgi_attr/uwsgi_val;
char *uwsgi_val = malloc(bervalues[0]->bv_len + 1);
if (!uwsgi_val) {
uwsgi_error("malloc()");
exit(1);
}
memcpy(uwsgi_val, bervalues[0]->bv_val, bervalues[0]->bv_len);
uwsgi_val[bervalues[0]->bv_len] = 0;
add_exported_option((char *) uwsgi_attr, uwsgi_val, 0);
free(bervalues);
}
else {
free(uwsgi_attr);
}
}
free(attr);
}
if (!found) {
uwsgi_log("no uWSGI LDAP entry found\n");
exit(1);
}
free(ber);
free(results);
ldap_unbind_ext_s(ldp, NULL, NULL);
}
#endif
-1201
View File
File diff suppressed because it is too large Load Diff
+20 -153
View File
@@ -91,6 +91,7 @@ retry:
}
#ifdef EOWNERDEAD
#ifndef PTHREAD_MUTEX_ROBUST
#define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP
#endif
@@ -401,60 +402,6 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
#elif defined(UWSGI_LOCK_USE_WINDOWS_MUTEX)
#define UWSGI_LOCK_ENGINE_NAME "windows mutexes"
#define UWSGI_LOCK_SIZE sizeof(HANDLE)
#define UWSGI_RWLOCK_SIZE sizeof(HANDLE)
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
struct _SECURITY_ATTRIBUTES sa;
memset(&sa, 0, sizeof(struct _SECURITY_ATTRIBUTES));
sa.bInheritHandle = 1;
uli->lock_ptr = CreateMutex(&sa, FALSE, NULL);
return uli;
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
WaitForSingleObject(uli->lock_ptr, INFINITE);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
ReleaseMutex(uli->lock_ptr);
uli->pid = 0;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (WaitForSingleObject(uli->lock_ptr, 0) == WAIT_TIMEOUT) {
return 0;
}
return uli->pid;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
return uwsgi_lock_fast_init(id);
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_lock_fast(uli);
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_fast_check(uli);
}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
uwsgi_unlock_fast(uli);
}
#else
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
@@ -474,6 +421,8 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
#define UWSGI_IPCSEM_ATEXIT 1
#endif
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
@@ -493,7 +442,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
if (uwsgi.ftok) {
myKey = ftok(uwsgi.ftok, counter);
if (myKey < 0) {
uwsgi_error("uwsgi_lock_ipcsem_init()/ftok()");
uwsgi_error("ftok()");
exit(1);
}
counter++;
@@ -504,7 +453,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
}
if (semid < 0) {
uwsgi_error("uwsgi_lock_ipcsem_init()/semget()");
uwsgi_error("semget()");
exit(1);
}
// do this now, to allows triggering of atexit hook in case of problems
@@ -512,7 +461,7 @@ struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
semu.val = 1;
if (semctl(semid, 0, SETVAL, semu)) {
uwsgi_error("uwsgi_lock_ipcsem_init()/semctl()");
uwsgi_error("semctl()");
exit(1);
}
@@ -531,14 +480,8 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
retry:
if (semop(semid, &sb, 1)) {
if (errno == EINTR) goto retry;
uwsgi_error("uwsgi_lock_ipcsem()/semop()");
#ifdef EIDRM
if (errno == EIDRM) {
exit(UWSGI_BRUTAL_RELOAD_CODE);
}
#endif
exit(1);
if (errno == EINTR) goto retry;
uwsgi_error("semop()");
}
}
@@ -554,14 +497,8 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
retry:
if (semop(semid, &sb, 1)) {
if (errno == EINTR) goto retry;
uwsgi_error("uwsgi_unlock_ipcsem()/semop()");
#ifdef EIDRM
if (errno == EIDRM) {
exit(UWSGI_BRUTAL_RELOAD_CODE);
}
#endif
exit(1);
if (errno == EINTR) goto retry;
uwsgi_error("semop()");
}
}
@@ -586,8 +523,6 @@ pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
void uwsgi_ipcsem_clear(void) {
if (uwsgi.persistent_ipcsem) return;
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uwsgi.workers)
@@ -608,27 +543,12 @@ clear:
#ifdef UWSGI_DEBUG
uwsgi_log("removing sysvipc semaphores...\n");
#endif
#ifdef GETPID
while (uli) {
int semid = 0;
memcpy(&semid, uli->lock_ptr, sizeof(int));
int ret = semctl(semid, 0, GETPID);
if (ret > 0) {
if (ret != (int) getpid() && !kill((pid_t) ret, 0)) {
uwsgi_log("found ipcsem mapped to alive pid %d. skipping ipcsem removal.\n", ret);
return;
}
}
uli = uli->next;
}
uli = uwsgi.registered_locks;
#endif
while (uli) {
int semid = 0;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semctl(semid, 0, IPC_RMID)) {
uwsgi_error("uwsgi_ipcsem_clear()/semctl()");
uwsgi_error("semctl()");
}
uli = uli->next;
}
@@ -639,39 +559,9 @@ pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
return uwsgi_lock_ipcsem_check(uli);
}
#ifdef UNBIT
/*
Unbit-specific workaround for robust-mutexes
*/
void *uwsgi_robust_mutexes_watchdog_loop(void *arg) {
for(;;) {
uwsgi_lock(uwsgi.the_thunder_lock);
uwsgi_unlock(uwsgi.the_thunder_lock);
}
return NULL;
}
void uwsgi_robust_mutexes_watchdog() {
pthread_t tid;
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
// 32K should be more than enough...
pthread_attr_setstacksize(&attr, 32 * 1024);
if (pthread_create(&tid, &attr, uwsgi_robust_mutexes_watchdog_loop, NULL)) {
uwsgi_error("uwsgi_robust_mutexes_watchdog()/pthread_create()");
exit(1);
}
}
#endif
void uwsgi_setup_locking() {
int i;
if (uwsgi.locking_setup) return;
// use the fastest available locking
if (uwsgi.lock_engine) {
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
@@ -710,13 +600,12 @@ void uwsgi_setup_locking() {
uwsgi.lock_size = UWSGI_LOCK_SIZE;
uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;
ready:
// application generic lock
int i;
ready:
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
for (i = 0; i < uwsgi.locks + 1; i++) {
char *num = uwsgi_num2str(i);
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", num));
free(num);
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
}
// event queue lock (mitigate same event on multiple queues)
@@ -734,6 +623,9 @@ ready:
// timer table lock
uwsgi.timer_table_lock = uwsgi_lock_init("timer");
// probe table lock
uwsgi.probe_table_lock = uwsgi_lock_init("probe");
// rb_timer table lock
uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");
@@ -743,28 +635,11 @@ ready:
if (uwsgi.use_thunder_lock) {
// process shared thunder lock
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
#ifdef UNBIT
// we have a serious bug on Unbit (and very probably on older libc)
// when all of the workers die in the same moment the pthread robust mutes is left
// in inconsistent state and we have no way to recover
// we span a thread in the master constantly ensuring the lock is ok
// for now we apply it only for Unbit (where thunder-lock is automatically enabled)
uwsgi_robust_mutexes_watchdog();
#endif
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
#ifdef UWSGI_SSL
// register locking for legions
struct uwsgi_legion *ul = uwsgi.legions;
while(ul) {
ul->lock = uwsgi_lock_init(uwsgi_concat2("legion_", ul->legion));
ul = ul->next;
}
#endif
uwsgi.locking_setup = 1;
}
@@ -827,18 +702,10 @@ nextlock:
}
int uwsgi_user_lock(int lock_num) {
if (lock_num < 0 || lock_num > uwsgi.locks) {
return -1;
}
void uwsgi_user_lock(int lock_num) {
uwsgi_lock(uwsgi.user_lock[lock_num]);
return 0;
}
int uwsgi_user_unlock(int lock_num) {
if (lock_num < 0 || lock_num > uwsgi.locks) {
return -1;
}
void uwsgi_user_unlock(int lock_num) {
uwsgi_unlock(uwsgi.user_lock[lock_num]);
return 0;
}
+199 -922
View File
File diff suppressed because it is too large Load Diff
+6 -1
View File
@@ -64,10 +64,12 @@ void simple_loop() {
void uwsgi_loop_cores_run(void *(*func) (void *)) {
int i;
#ifdef UWSGI_THREADING
for (i = 1; i < uwsgi.threads; i++) {
long j = i;
pthread_create(&uwsgi.workers[uwsgi.mywid].cores[i].thread_id, &uwsgi.threads_attr, func, (void *) j);
}
#endif
long y = 0;
func((void *) y);
}
@@ -118,9 +120,12 @@ void *simple_loop_run(void *arg1) {
struct wsgi_request *wsgi_req = &uwsgi.workers[uwsgi.mywid].cores[core_id].req;
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) {
uwsgi_setup_thread_req(core_id, wsgi_req);
}
#endif
// initialize the main event queue to monitor sockets
int main_queue = event_queue_init();
@@ -141,7 +146,7 @@ void *simple_loop_run(void *arg1) {
continue;
}
if (wsgi_req_recv(main_queue, wsgi_req)) {
if (wsgi_req_recv(wsgi_req)) {
uwsgi_destroy_request(wsgi_req);
continue;
}
+927 -269
View File
File diff suppressed because it is too large Load Diff
-338
View File
@@ -1,338 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
// check if all of the workers are dead and exit uWSGI
void uwsgi_master_check_death() {
if (uwsgi_instance_is_dying) {
int i;
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0) {
return;
}
}
uwsgi_log("goodbye to uWSGI.\n");
exit(0);
}
}
// check if all of the workers are dead, and trigger a reload
int uwsgi_master_check_reload(char **argv) {
if (uwsgi_instance_is_reloading) {
int i;
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0) {
return 0;
}
}
uwsgi_reload(argv);
// never here (unless in shared library mode)
return -1;
}
return 0;
}
// check for chain reload
void uwsgi_master_check_chain() {
if (!uwsgi.status.chain_reloading) return;
int i;
int needed_procs = 0;
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0) {
needed_procs++;
}
}
if (uwsgi.status.chain_reloading > needed_procs) {
uwsgi.status.chain_reloading = 0;
uwsgi_log_verbose("chain reloading complete\n");
}
uwsgi_block_signal(SIGHUP);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
uwsgi_curse(i, SIGHUP);
break;
}
}
uwsgi_unblock_signal(SIGHUP);
}
// special function for assuming all of the workers are dead
void uwsgi_master_commit_status() {
int i;
for(i=1;i<=uwsgi.numproc;i++) {
uwsgi.workers[i].pid = 0;
}
}
void uwsgi_master_check_idle() {
static time_t last_request_timecheck = 0;
static uint64_t last_request_count = 0;
int i;
int waitpid_status;
if (!uwsgi.idle || uwsgi.status.is_cheap)
return;
uwsgi.current_time = uwsgi_now();
if (!last_request_timecheck)
last_request_timecheck = uwsgi.current_time;
// security check, stop the check if there are busy workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi_worker_is_busy(i)) {
return;
}
}
}
if (last_request_count != uwsgi.workers[0].requests) {
last_request_timecheck = uwsgi.current_time;
last_request_count = uwsgi.workers[0].requests;
}
// a bit of over-engeneering to avoid clock skews
else if (last_request_timecheck < uwsgi.current_time && (uwsgi.current_time - last_request_timecheck > uwsgi.idle)) {
uwsgi_log("workers have been inactive for more than %d seconds (%llu-%llu)\n", uwsgi.idle, (unsigned long long) uwsgi.current_time, (unsigned long long) last_request_timecheck);
uwsgi.status.is_cheap = 1;
if (uwsgi.die_on_idle) {
if (uwsgi.has_emperor) {
char byte = 22;
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
uwsgi_error("write()");
kill_them_all(0);
}
}
else {
kill_them_all(0);
}
return;
}
for (i = 1; i <= uwsgi.numproc; i++) {
uwsgi.workers[i].cheaped = 1;
if (uwsgi.workers[i].pid == 0)
continue;
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
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");
last_request_timecheck = 0;
}
}
void uwsgi_master_check_workers_deadline() {
int i;
for (i = 1; i <= uwsgi.numproc; i++) {
/* first check for harakiri */
if (uwsgi.workers[i].harakiri > 0) {
if (uwsgi.workers[i].harakiri < (time_t) uwsgi.current_time) {
trigger_harakiri(i);
}
}
/* then user-defined harakiri */
if (uwsgi.workers[i].user_harakiri > 0) {
if (uwsgi.workers[i].user_harakiri < (time_t) uwsgi.current_time) {
trigger_harakiri(i);
}
}
// then for evil memory checkers
if (uwsgi.evil_reload_on_as) {
if ((rlim_t) uwsgi.workers[i].vsz_size >= uwsgi.evil_reload_on_as) {
uwsgi_log("*** EVIL RELOAD ON WORKER %d ADDRESS SPACE: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].vsz_size, uwsgi.workers[i].pid);
kill(uwsgi.workers[i].pid, SIGKILL);
uwsgi.workers[i].vsz_size = 0;
}
}
if (uwsgi.evil_reload_on_rss) {
if ((rlim_t) uwsgi.workers[i].rss_size >= uwsgi.evil_reload_on_rss) {
uwsgi_log("*** EVIL RELOAD ON WORKER %d RSS: %lld (pid: %d) ***\n", i, (long long) uwsgi.workers[i].rss_size, uwsgi.workers[i].pid);
kill(uwsgi.workers[i].pid, SIGKILL);
uwsgi.workers[i].rss_size = 0;
}
}
// check if worker was running longer than allowed lifetime
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] > 0) {
uint64_t lifetime = uwsgi_now() - uwsgi.workers[i].last_spawn;
if (lifetime > uwsgi.shared->options[UWSGI_OPTION_MAX_WORKER_LIFETIME] && uwsgi.workers[i].manage_next_request == 1) {
uwsgi_log("worker %d lifetime reached, it was running for %llu second(s)\n", i, (unsigned long long) lifetime);
uwsgi.workers[i].manage_next_request = 0;
kill(uwsgi.workers[i].pid, SIGWINCH);
}
}
// need to find a better way
//uwsgi.workers[i].last_running_time = uwsgi.workers[i].running_time;
}
}
void uwsgi_master_check_gateways_deadline() {
int i;
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways_harakiri[i] > 0) {
if (ushared->gateways_harakiri[i] < (time_t) uwsgi.current_time) {
if (ushared->gateways[i].pid > 0) {
uwsgi_log("*** HARAKIRI ON GATEWAY %s %d (pid: %d) ***\n", ushared->gateways[i].name, ushared->gateways[i].num, ushared->gateways[i].pid);
kill(ushared->gateways[i].pid, SIGKILL);
}
ushared->gateways_harakiri[i] = 0;
}
}
}
}
void uwsgi_master_check_mules_deadline() {
int i;
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].harakiri > 0) {
if (uwsgi.mules[i].harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON MULE %d HANDLING SIGNAL %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].signum, uwsgi.mules[i].pid);
kill(uwsgi.mules[i].pid, SIGKILL);
uwsgi.mules[i].harakiri = 0;
}
}
// user harakiri
if (uwsgi.mules[i].user_harakiri > 0) {
if (uwsgi.mules[i].user_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON MULE %d (pid: %d) ***\n", i + 1, uwsgi.mules[i].pid);
kill(uwsgi.mules[i].pid, SIGKILL);
uwsgi.mules[i].user_harakiri = 0;
}
}
}
}
void uwsgi_master_check_spoolers_deadline() {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
if (uspool->harakiri > 0 && uspool->harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
kill(uspool->pid, SIGKILL);
uspool->harakiri = 0;
}
if (uspool->user_harakiri > 0 && uspool->user_harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON THE SPOOLER (pid: %d) ***\n", uspool->pid);
kill(uspool->pid, SIGKILL);
uspool->user_harakiri = 0;
}
uspool = uspool->next;
}
}
int uwsgi_master_check_spoolers_death(int diedpid) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
if (uspool->pid > 0 && diedpid == uspool->pid) {
uwsgi_log("OOOPS the spooler is no more...trying respawn...\n");
uspool->respawned++;
uspool->pid = spooler_start(uspool);
return -1;
}
uspool = uspool->next;
}
return 0;
}
int uwsgi_master_check_emperor_death(int diedpid) {
if (uwsgi.emperor_pid >= 0 && diedpid == uwsgi.emperor_pid) {
uwsgi_log_verbose("!!! Emperor died !!!\n");
uwsgi_emperor_start();
return -1;
}
return 0;
}
int uwsgi_master_check_mules_death(int diedpid) {
int i;
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].pid == diedpid) {
uwsgi_log("OOOPS mule %d (pid: %d) crippled...trying respawn...\n", i + 1, uwsgi.mules[i].pid);
uwsgi_mule(i + 1);
return -1;
}
}
return 0;
}
int uwsgi_master_check_gateways_death(int diedpid) {
int i;
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid == diedpid) {
gateway_respawn(i);
return -1;
}
}
return 0;
}
int uwsgi_master_check_daemons_death(int diedpid) {
/* reload the daemons */
if (uwsgi_daemon_check_pid_reload(diedpid)) {
return -1;
}
return 0;
}
int uwsgi_worker_is_busy(int wid) {
int i;
for(i=0;i<uwsgi.cores;i++) {
if (uwsgi.workers[wid].cores[i].in_request) {
return 1;
}
}
return 0;
}
int uwsgi_master_check_cron_death(int diedpid) {
struct uwsgi_cron *uc = uwsgi.crons;
while (uc) {
if (uc->pid == (pid_t) diedpid) {
uwsgi_log("[uwsgi-cron] command \"%s\" running with pid %d exited after %d second(s)\n", uc->command, uc->pid, uwsgi_now() - uc->started_at);
uc->pid = -1;
uc->started_at = 0;
return -1;
}
uc = uc->next;
}
return 0;
}
void uwsgi_master_check_crons_deadline() {
struct uwsgi_cron *uc = uwsgi.crons;
while (uc) {
if (uc->pid >= 0 && uc->harakiri > 0 && uc->harakiri < (time_t) uwsgi.current_time) {
uwsgi_log("*** HARAKIRI ON CRON \"%s\" (pid: %d) ***\n", uc->command, uc->pid);
kill(-uc->pid, SIGKILL);
}
uc = uc->next;
}
}
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);
}
}
}
-256
View File
@@ -1,256 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int uwsgi_master_manage_events(int interesting_fd) {
// is a logline ?
if (uwsgi.log_master && !uwsgi.threaded_logger) {
// stderr log ?
if (interesting_fd == uwsgi.shared->worker_log_pipe[0]) {
uwsgi_master_log();
return 0;
}
// req log ?
if (uwsgi.req_log_master && interesting_fd == uwsgi.shared->worker_req_log_pipe[0]) {
uwsgi_master_req_log();
return 0;
}
}
if (uwsgi.master_fifo_fd > -1 && interesting_fd == uwsgi.master_fifo_fd) {
return uwsgi_master_fifo_manage(uwsgi.master_fifo_fd);
}
// stats server ?
if (uwsgi.stats && uwsgi.stats_fd > -1) {
if (interesting_fd == uwsgi.stats_fd) {
uwsgi_send_stats(uwsgi.stats_fd, uwsgi_master_generate_stats);
return 0;
}
}
// a zerg connection ?
if (uwsgi.zerg_server) {
if (interesting_fd == uwsgi.zerg_server_fd) {
uwsgi_manage_zerg(uwsgi.zerg_server_fd, 0, NULL);
return 0;
}
}
// 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;
}
}
if (uwsgi_fsmon_event(interesting_fd)) {
return 0;
}
// reload on fd
if (uwsgi.reload_on_fd) {
// custom -> fd
// custom2 -> len (optional, default 1)
// custom_ptr -> log message (optional)
struct uwsgi_string_list *usl = uwsgi.reload_on_fd;
while(usl) {
if (interesting_fd == (int) usl->custom) {
char stack_tmp[8];
char *tmp = stack_tmp;
if (usl->custom2 > 8) {
tmp = uwsgi_malloc(usl->custom2);
}
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
uwsgi_error("[reload-on-fd] read()");
}
if (usl->custom_ptr) {
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
}
else {
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
}
uwsgi_block_signal(SIGHUP);
grace_them_all(0);
uwsgi_unblock_signal(SIGHUP);
return 0;
}
usl = usl->next;
}
}
// brutal reload on fd
if (uwsgi.brutal_reload_on_fd) {
// custom -> fd
// custom2 -> len (optional, default 1)
// custom_ptr -> log message (optional)
struct uwsgi_string_list *usl = uwsgi.brutal_reload_on_fd;
while(usl) {
if (interesting_fd == (int) usl->custom) {
char stack_tmp[8];
char *tmp = stack_tmp;
if (usl->custom2 > 8) {
tmp = uwsgi_malloc(usl->custom2);
}
if (read(interesting_fd, tmp, usl->custom2) <= 0) {
uwsgi_error("[brutal-reload-on-fd] read()");
}
if (usl->custom_ptr) {
uwsgi_log_verbose("*** fd %d ready: %s ***\n", interesting_fd, usl->custom_ptr);
}
else {
uwsgi_log_verbose("*** fd %d ready !!! ***\n", interesting_fd);
}
if (uwsgi.die_on_term) {
uwsgi_block_signal(SIGQUIT);
reap_them_all(0);
uwsgi_unblock_signal(SIGQUIT);
}
else {
uwsgi_block_signal(SIGTERM);
reap_them_all(0);
uwsgi_unblock_signal(SIGTERM);
}
return 0;
}
usl = usl->next;
}
}
// wakeup from cheap mode ?
if (uwsgi.status.is_cheap) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
uwsgi.status.is_cheap = 0;
uwsgi_del_sockets_from_queue(uwsgi.master_queue);
// how many worker we need to respawn ?
int needed = uwsgi.numproc;
// if in cheaper mode, just respawn the minimal amount
if (uwsgi.cheaper) {
needed = uwsgi.cheaper_count;
}
int i;
for (i = 1; i <= needed; i++) {
if (uwsgi_respawn_worker(i))
return -1;
}
// here we continue instead of returning
break;
}
uwsgi_sock = uwsgi_sock->next;
}
}
// an SNMP request ?
if (uwsgi.snmp_addr && interesting_fd == uwsgi.snmp_fd) {
uwsgi_master_manage_snmp(uwsgi.snmp_fd);
return 0;
}
// a UDP request ?
if (uwsgi.udp_socket && interesting_fd == uwsgi.udp_fd) {
uwsgi_master_manage_udp(uwsgi.udp_fd);
return 0;
}
// check if some file monitor is ready
// no need to lock as we are only getting registered items (and only the master can register them)
int i;
for (i = 0; i < ushared->files_monitored_cnt; i++) {
if (ushared->files_monitored[i].registered) {
if (interesting_fd == ushared->files_monitored[i].fd) {
struct uwsgi_fmon *uf = event_queue_ack_file_monitor(uwsgi.master_queue, interesting_fd);
// now call the file_monitor handler
if (uf)
uwsgi_route_signal(uf->sig);
return 0;
}
}
}
// check if some timer elapsed
// no need to lock again
for (i = 0; i < ushared->timers_cnt; i++) {
if (ushared->timers[i].registered) {
if (interesting_fd == ushared->timers[i].fd) {
struct uwsgi_timer *ut = event_queue_ack_timer(interesting_fd);
// now call the timer handler
if (ut)
uwsgi_route_signal(ut->sig);
return 0;
}
}
}
uint8_t uwsgi_signal;
// check for worker signal
if (interesting_fd == uwsgi.shared->worker_signal_pipe[0]) {
ssize_t rlen = read(interesting_fd, &uwsgi_signal, 1);
if (rlen < 0) {
uwsgi_error("uwsgi_master_manage_events()/read()");
}
else if (rlen > 0) {
uwsgi_route_signal(uwsgi_signal);
}
else {
// TODO restart workers here
uwsgi_log_verbose("lost connection with workers !!!\n");
close(interesting_fd);
}
return 0;
}
// check for spooler signal
if (uwsgi.spoolers) {
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[0]) {
ssize_t rlen = read(interesting_fd, &uwsgi_signal, 1);
if (rlen < 0) {
uwsgi_error("uwsgi_master_manage_events()/read()");
}
else if (rlen > 0) {
uwsgi_route_signal(uwsgi_signal);
}
else {
// TODO restart spoolers here
uwsgi_log_verbose("lost connection with spoolers\n");
close(interesting_fd);
}
return 0;
}
}
// check for mules signal
if (uwsgi.mules_cnt > 0) {
if (interesting_fd == uwsgi.shared->mule_signal_pipe[0]) {
ssize_t rlen = read(interesting_fd, &uwsgi_signal, 1);
if (rlen < 0) {
uwsgi_error("uwsgi_master_manage_events()/read()");
}
else if (rlen > 0) {
uwsgi_route_signal(uwsgi_signal);
}
else {
// TODO respawn mules here
uwsgi_log_verbose("lost connection with mules\n");
close(interesting_fd);
}
// return 0;
}
}
return 0;
}
+265 -628
View File
File diff suppressed because it is too large Load Diff
-138
View File
@@ -1,138 +0,0 @@
/*
uWSGI metrics subsystem
a metric is a node in a tree reachable via a numeric id (OID, in SNMP way) or a simple string:
uwsgi.worker.1.requests
uwsgi.custom.foo.bar
the oid representation:
1.3.6.1.4.1.35156.17 = iso.org.dod.internet.private.enterprise.unbit.uwsgi
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
1.3.6.1.4.1.35156.17.3.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.requests
1.3.6.1.4.1.35156.17.3.1.2.1.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.worker.1.core.1.requests
1.3.6.1.4.1.35156.17.4.1 = iso.org.dod.internet.private.enterprise.unbit.uwsgi.system.load_avg
...
each metric is a collected value with a specific frequency (a frequency of zero means the value is re-computed every time)
metrics are meant for numeric values signed 64 bit, but they can be exposed as:
gauge
counter
absolute
both 32 and 64bit, both signed and unsigned
metrics are managed by a dedicated thread (in the master) holding a linked list of all the items. For few metrics it is a good (read: simple) approach,
but you can cache lookups in a uWSGI cache for really big list.
struct uwsgi_metric *um = uwsgi_register_metric("worker.1.requests", "3.1.1", UWSGI_METRIC_COUNTER, UWSGI_METRIC_PTR, &uwsgi.workers[1].requests, 0, NULL);
prototype: struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom);
value_type = UWSGI_METRIC_COUNTER/UWSGI_METRIC_GAUGE/UWSGI_METRIC_ABSOLUTE
collect_way = UWSGI_METRIC_PTR -> get from a pointer / UWSGI_METRIC_FUNC -> get from a func with the prototype int64_t func(struct uwsgi_metric *); / UWSGI_METRIC_FILE -> get the value from a file, ptr is the filename
when freq is zero the value is recomputed whenever requested, otherwise the metrics thread compute it every time the frequency is elapsed and caches it
For some metric (or all ?) you may want to hold a value even after a server reload. For such a reason you can specify a directory on wich the server (on startup/restart) will look for
a file named like the metric and will read the initial value from it. It may look an old-fashioned and quite inefficient way, but it is the most versatile for a sysadmin (allowing him/her
to even modify the values manually)
When registering a metric with the same name of an already registered one, the new one will overwrite the previous one. This allows plugins writer to override default behaviours
Applications are allowed to update metrics (but they cannot register new ones), with simple api funcs:
uwsgi.metric_set("worker.1.requests", N)
uwsgi.metric_inc("worker.1.requests", N=1)
uwsgi.metric_dec("worker.1.requests", N=1)
uwsgi.metric_mul("worker.1.requests", N=1)
uwsgi.metric_div("worker.1.requests", N=1)
and obviously they can get values:
uwsgi.metric_get("worker.1.requests", no_cache|force=False)
if the second parameter is True, the value is recomputed (but if it is a metric with a cache, the cache value will not be updated accordingly, this is the job of the metric thread)
Updating metrics from your app MUST BE ATOMIC, for such a reason a uWSGI rwlock is initialized on startup and used for each operation (simple reading from a metric does not require locking)
Metrics can be updated from the internal routing subsystem too:
route-if = equal:${REQUEST_URI};/foobar metricinc:foobar.test 2
and can be accessed as ${metric[foobar.test]}
The stats server exports the metrics list in the "metrics" attribute (obviously some info could be redundant)
*/
struct uwsgi_metric {
char *name;
char *oid;
// pre-computed snmp representation
char *asn;
size_t asn_size;
// ABSOLUTE/COUNTER/GAUGE
uint8_t type;
// MANUAL/PTR/FUNC/FILE
uint8_t collect_way
// this could be taken from a file storage and must laways be added to value when reporting (default 0)
int64_t initial_value;
// the value of the metric (point to a shared memory area)
*int64_t value;
// a custom blob you can attach to a metric
void *custom;
// the collection frequency
uint32_t freq;
time_t last_update;
// run this function to collect the value
int64_t (*collector)(struct uwsgi_metric *);
// take the value from this pointer to a 64bit value
int64_t *ptr;
// get the initial value from this file, and store each update in it
char *filename;
struct uwsgi_metric *next;
};
struct uwsgi_metric *uwsgi_register_metric(char *name, char *oid, uint8_t value_type, uint8_t collect_way, void *ptr, uint32_t freq, void *custom) {
struct uwsgi_metric *old_metric=NULL,*metric=uwsgi.metric;
while(metric) {
metric = metric->next;
}
}
void uwsgi_metric_loop() {
// every second scan the whole metrics tree
time_t now = uwsgi_now();
}
int64_t uwsgi_metric_get(char *name, char *oid) {
struct uwsgi_metric *um = NULL;
if (name) {
um = uwsgi_metric_find_by_name(name);
}
else if (oid) {
um = uwsgi_metric_find_by_oid(oid);
}
if (!um) return 0;
//
switch(um->collect_way) {
case UWSGI_METRIC_MANUAL:
return um->initial_value+*um->value;
case UWSGI_METRIC_PTR:
return um->initial_value+*um->ptr;
case UWSGI_METRIC_FUNC:
case UWSGI_METRIC_FILE:
}
}
-254
View File
@@ -1,254 +0,0 @@
#include <uwsgi.h>
/*
jail systems (Linux namespaces, FreeBSD jails...) heavily rely on mount/umount
to simplify setups (expecially because the mount command could not be available in
the initial phase of jailing, we need an api to mount/umount filesystems
int uwsgi_mount(char *fs, char *what, char *where, int flags);
int uwsgi_umount(char *where, int flags);
*/
#ifdef __linux__
#ifndef MS_REC
#define MS_REC 16384
#endif
#include <sys/statfs.h>
#endif
struct uwsgi_mount_flag {
char *key;
uint64_t value;
};
static struct uwsgi_mount_flag umflags[] = {
#ifdef MS_BIND
{"bind", MS_BIND},
#endif
#ifdef MS_DIRSYNC
{"dirsync", MS_DIRSYNC},
#endif
#ifdef MS_MANDLOCK
{"mandlock", MS_MANDLOCK},
#endif
#ifdef MS_MOVE
{"move", MS_MOVE},
#endif
#ifdef MS_NOATIME
{"noatime", MS_NOATIME},
#endif
#ifdef MS_NODEV
{"nodev", MS_NODEV},
#endif
#ifdef MS_NOEXEC
{"noexec", MS_NOEXEC},
#endif
#ifdef MS_RDONLY
{"rdonly", MS_RDONLY},
{"readonly", MS_RDONLY},
{"ro", MS_RDONLY},
#endif
#ifdef MS_REMOUNT
{"remount", MS_REMOUNT},
#endif
#ifdef MS_SYNCHRONOUS
{"sync", MS_SYNCHRONOUS},
#endif
#ifdef MNT_FORCE
{"force", MNT_FORCE},
#endif
#ifdef MNT_DETACH
{"detach", MNT_DETACH},
#endif
#ifdef MS_REC
{"rec", MS_REC},
{"recursive", MS_REC},
#endif
#ifdef MS_PRIVATE
{"private", MS_PRIVATE},
#endif
#ifdef MS_SHARED
{"shared", MS_SHARED},
#endif
#ifdef MNT_RDONLY
{"rdonly", MNT_RDONLY},
{"readonly", MNT_RDONLY},
{"ro", MNT_RDONLY},
#endif
#ifdef MNT_NOEXEC
{"noexec", MNT_NOEXEC},
#endif
#ifdef MNT_NOSUID
{"nosuid", MNT_NOSUID},
#endif
#ifdef MNT_NOATIME
{"noatime", MNT_NOATIME},
#endif
#ifdef MNT_SNAPSHOT
{"snapshot", MNT_SNAPSHOT},
#endif
{NULL, 0},
};
uint64_t uwsgi_mount_flag(char *mflag) {
struct uwsgi_mount_flag *umf = umflags;
while(umf->key) {
if (!strcmp(umf->key, mflag)) return umf->value;
umf++;
}
return 0;
}
int uwsgi_mount(char *fs, char *what, char *where, char *flags) {
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
struct iovec iov[6];
#endif
unsigned long mountflags = 0;
if (!flags) goto parsed;
char *mflags = uwsgi_str(flags);
char *p, *ctx = NULL;
uwsgi_foreach_token(mflags, ",", p, ctx) {
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
if (!flag) {
uwsgi_log("unknown mount flag \"%s\"\n", p);
exit(1);
}
mountflags |= flag;
}
free(mflags);
parsed:
#ifdef __linux__
return mount(what, where, fs, mountflags, NULL);
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
iov[0].iov_base = "fstype";
iov[0].iov_len = 7;
iov[1].iov_base = fs;
iov[1].iov_len = strlen(fs) + 1;
iov[2].iov_base = "fspath";
iov[2].iov_len = 7;
iov[3].iov_base = where;
iov[3].iov_len = strlen(where) + 1;
iov[4].iov_base = "target";
iov[4].iov_len = 7;
iov[5].iov_base = what;
iov[5].iov_len = strlen(what) + 1;
return nmount(iov, 6, (int) mountflags);
#endif
return -1;
}
int uwsgi_umount(char *where, char *flags) {
unsigned long mountflags = 0;
if (!flags) goto parsed;
char *mflags = uwsgi_str(flags);
char *p, *ctx = NULL;
uwsgi_foreach_token(mflags, ",", p, ctx) {
unsigned long flag = (unsigned long) uwsgi_mount_flag(p);
if (!flag) {
uwsgi_log("unknown umount flag \"%s\"\n", p);
exit(1);
}
mountflags |= flag;
}
free(mflags);
parsed:
#ifdef __linux__
// we need a special case for recursive umount
if (mountflags & MS_REC) {
mountflags &= ~MS_REC;
int unmounted = 1;
char *slashed = uwsgi_concat2(where, "/");
while (unmounted) {
unmounted = 0;
FILE *procmounts = fopen("/proc/self/mounts", "r");
if (!procmounts) {
uwsgi_log("the /proc filesystem must be mounted for recursive umount\n");
uwsgi_error("open()");
exit(1);
}
char line[1024];
while (fgets(line, 1024, procmounts) != NULL) {
char *delim0 = strchr(line, ' ');
if (!delim0) continue;
delim0++;
char *delim1 = strchr(delim0, ' ');
if (!delim1) continue;
*delim1 = 0;
if (!uwsgi_starts_with(delim0, strlen(delim0), slashed, strlen(slashed))) goto unmountable;
continue;
unmountable:
if (!umount2(delim0, mountflags)) unmounted++;
}
fclose(procmounts);
}
free(slashed);
}
return umount2(where, mountflags);
#elif defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
return unmount(where, mountflags);
#endif
return -1;
}
int uwsgi_mount_hook(char *arg) {
char *tmp_arg = uwsgi_str(arg);
char *fs = tmp_arg;
char *what = strchr(fs, ' ');
if (!what) goto error;
*what = 0; what++;
char *where = strchr(what, ' ');
if (!where) goto error;
*where = 0; where++;
char *flags = strchr(where, ' ');
if (flags) {
*flags = 0; flags++;
}
if (uwsgi_mount(fs, what, where, flags)) {
uwsgi_error("uwsgi_mount()");
free(tmp_arg);
return -1;
}
free(tmp_arg);
return 0;
error:
free(tmp_arg);
uwsgi_log("uwsgi_mount_hook() invalid syntax\n");
return -1;
}
int uwsgi_umount_hook(char *arg) {
char *tmp_arg = uwsgi_str(arg);
char *where = tmp_arg;
char *flags = strchr(where, ' ');
if (flags) {
*flags = 0; flags++;
}
if (uwsgi_umount(where, flags)) {
uwsgi_error("uwsgi_umount()");
free(tmp_arg);
return -1;
}
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
}
+20 -30
View File
@@ -56,7 +56,6 @@ void uwsgi_mule(int id) {
// avoid race conditions
uwsgi.mules[id - 1].id = id;
uwsgi.mules[id - 1].pid = getpid();
uwsgi.mypid = uwsgi.mules[id - 1].pid;
uwsgi_fixup_fds(0, id, NULL);
@@ -77,8 +76,19 @@ void uwsgi_mule(int id) {
}
}
uwsgi_mule_run();
if (uwsgi.mules[id - 1].patch) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
// never here
end_me(1);
}
}
}
}
uwsgi_mule_handler();
}
else if (pid > 0) {
uwsgi.mules[id - 1].id = id;
@@ -87,23 +97,6 @@ void uwsgi_mule(int id) {
}
}
void uwsgi_mule_run() {
int id = uwsgi.muleid;
int i;
if (uwsgi.mules[id - 1].patch) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
// never here ?
end_me(1);
}
}
}
}
uwsgi_mule_handler();
}
int uwsgi_farm_has_mule(struct uwsgi_farm *farm, int muleid) {
struct uwsgi_mule_farm *umf = farm->mules;
@@ -190,7 +183,6 @@ void uwsgi_mule_handler() {
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) continue;
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
@@ -204,9 +196,7 @@ void uwsgi_mule_handler() {
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
len = read(interesting_fd, message, 65536);
if (len < 0) {
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
uwsgi_error("uwsgi_mule_handler/read()");
}
uwsgi_error("read()");
}
else {
int i, found = 0;
@@ -219,7 +209,7 @@ void uwsgi_mule_handler() {
}
}
if (!found)
uwsgi_log("*** mule %d received a %ld bytes message ***\n", uwsgi.muleid, (long) len);
uwsgi_log("*** mule %d received a %d bytes message ***\n", uwsgi.muleid, len);
}
}
}
@@ -352,7 +342,6 @@ next:
if (interesting_fd > -1) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
@@ -360,7 +349,7 @@ next:
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
}
// set the error condition
len = -1;
@@ -447,14 +436,13 @@ void uwsgi_setup_mules_and_farms() {
mules_list++;
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
// create the socket pipe
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
char *p, *ctx = NULL;
uwsgi_foreach_token(mules_list, ",", p, ctx) {
char *p = strtok(mules_list, ",");
while (p != NULL) {
struct uwsgi_mule *um = get_mule_by_id(atoi(p));
if (!um) {
uwsgi_log("invalid mule id: %s\n", p);
@@ -462,11 +450,13 @@ void uwsgi_setup_mules_and_farms() {
}
uwsgi_mule_farm_new(&uwsgi.farms[i].mules, um);
p = strtok(NULL, ",");
}
uwsgi_log("created farm %d name: %s mules:%s\n", i + 1, uwsgi.farms[i].name, strchr(farm_name->value, ':') + 1);
farm_name = farm_name->next;
free(farm_value);
}
}
+3 -6
View File
@@ -20,9 +20,7 @@ void uwsgi_systemd_notify(char *message) {
msghdr->msg_iovlen = 3;
if (sendmsg(uwsgi.notification_fd, msghdr, 0) < 0) {
uwsgi_error("sendmsg()");
}
sendmsg(uwsgi.notification_fd, msghdr, 0);
}
void uwsgi_systemd_notify_ready(void) {
@@ -35,9 +33,8 @@ void uwsgi_systemd_notify_ready(void) {
msghdr->msg_iovlen = 1;
if (sendmsg(uwsgi.notification_fd, msghdr, 0) < 0) {
uwsgi_error("sendmsg()");
}
sendmsg(uwsgi.notification_fd, msghdr, 0);
}
+75 -344
View File
@@ -4,17 +4,6 @@
uWSGI offloading subsystem
steps to offload a task
1) allocate a uwsgi_offload_request structure (could be on stack)
struct uwsgi_offload_request uor;
2) prepare it for a specific engine (last argument is the takeover flag)
uwsgi_offload_setup(my_engine, &uor, 1)
3) run it (last argument is the waiter)
int uwsgi_offload_run(wsgi_req, &uor, NULL);
between 2 and 3 you can set specific values
*/
@@ -24,20 +13,19 @@ extern struct uwsgi_server uwsgi;
#define uwsgi_offload_0r_1w(x, y) if (event_queue_del_fd(ut->queue, x, event_queue_read())) return -1;\
if (event_queue_fd_read_to_write(ut->queue, y)) return -1;
void uwsgi_offload_setup(struct uwsgi_offload_engine *uoe, struct uwsgi_offload_request *uor, struct wsgi_request *wsgi_req, uint8_t takeover) {
static int uwsgi_offload_net_transfer(struct uwsgi_thread *, struct uwsgi_offload_request *, int);
static int uwsgi_offload_sendfile_transfer(struct uwsgi_thread *, struct uwsgi_offload_request *, int);
static void uwsgi_offload_setup(struct uwsgi_offload_request *uor, struct wsgi_request *wsgi_req,
int (*func)(struct uwsgi_thread *, struct uwsgi_offload_request *, int)) {
wsgi_req->fd_closed = 1;
memset(uor, 0, sizeof(struct uwsgi_offload_request));
uor->engine = uoe;
uor->s = wsgi_req->fd;
uor->fd = -1;
uor->fd2 = -1;
// an engine could changes behaviour based on pipe anf takeover values
uor->pipe[0] = -1;
uor->pipe[1] = -1;
uor->takeover = takeover;
uor->s = wsgi_req->poll.fd;
uor->func = func;
// put socket in non-blocking mode
uwsgi_socket_nb(uor->s);
}
static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
@@ -50,125 +38,79 @@ static int uwsgi_offload_enqueue(struct wsgi_request *wsgi_req, struct uwsgi_off
struct uwsgi_thread *ut = uwsgi.offload_thread[uc->offload_rr];
uc->offload_rr++;
if (write(ut->pipe[0], uor, sizeof(struct uwsgi_offload_request)) != sizeof(struct uwsgi_offload_request)) {
if (uor->takeover) {
wsgi_req->fd_closed = 0;
}
return -1;
}
return 0;
}
/*
int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socket, struct uwsgi_buffer *ubuf) {
pipe offload engine:
fd -> the file descriptor to read from
len -> amount of data to transfer
// fill offload request
struct uwsgi_offload_request uor;
uwsgi_offload_setup(&uor, wsgi_req, uwsgi_offload_net_transfer);
*/
static int u_offload_pipe_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (uor->fd < 0 || !uor->len) {
return -1;
}
return 0;
}
/*
memory offload engine:
buf -> pointer to the memory to transfer (memory is freed at the end)
len -> amount of data to transfer
*/
static int u_offload_memory_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->buf || !uor->len) {
return -1;
}
return 0;
}
/*
transfer offload engine:
name -> socket name
ubuf -> data to send
*/
static int u_offload_transfer_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->name) {
return -1;
uor.fd = uwsgi_connect(socket, 0, 1);
if (uor.fd < 0) {
uwsgi_error("uwsgi_offload_request_net_do() -> connect()");
goto error;
}
uor->fd = uwsgi_connect(uor->name, 0, 1);
if (uor->fd < 0) {
uwsgi_error("u_offload_transfer_prepare()/connect()");
return -1;
uor.ubuf = ubuf;
if (uwsgi_offload_enqueue(wsgi_req, &uor)) {
goto error2;
}
return 0;
error2:
close(uor.fd);
error:
wsgi_req->fd_closed = 0;
return -1;
}
/*
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, char *filename, size_t len) {
sendfile offload engine:
name -> filename to transfer
fd -> file descriptor of file to transfer
fd2 -> sendfile destination (default wsgi_req->fd)
len -> size of the file or amount of data to transfer
pos -> position in the file
// fill offload request
struct uwsgi_offload_request uor;
uwsgi_offload_setup(&uor, wsgi_req, uwsgi_offload_sendfile_transfer);
*/
static int u_offload_sendfile_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {
if (!uor->name && uor->fd == -1) return -1;
if (uor->name) {
uor->fd = open(uor->name, O_RDONLY | O_NONBLOCK);
if (uor->fd < 0) {
uwsgi_error_open(uor->name);
return -1;
}
uor.fd = open(filename, O_RDONLY | O_NONBLOCK);
if (uor.fd < 0) {
uwsgi_error_open(filename);
goto error;
}
// make a fstat to get the file size
if (!uor->len) {
if (!len) {
struct stat st;
if (fstat(uor->fd, &st)) {
uwsgi_error("u_offload_sendfile_prepare()/fstat()");
if (uor->name) {
close(uor->fd);
}
return -1;
if (fstat(uor.fd, &st)) {
uwsgi_error("fstat()");
goto error2;
}
uor->len = st.st_size;
len = st.st_size;
}
if (uor->fd2 == -1) {
uor->fd2 = uor->s;
uor.len = len;
if (uwsgi_offload_enqueue(wsgi_req, &uor)) {
goto error2;
}
uor->s = -1;
return 0;
error2:
close(uor.fd);
error:
wsgi_req->fd_closed = 0;
return -1;
}
static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor) {
// close the socket and the file descriptor
if (uor->takeover && uor->s > -1) {
close(uor->s);
}
if (uor->fd != -1) {
close(uor->fd);
}
if (uor->fd2 != -1) {
close(uor->fd2);
}
close(uor->s);
close(uor->fd);
// remove the structure from the linked list;
struct uwsgi_offload_request *prev = uor->prev;
struct uwsgi_offload_request *next = uor->next;
@@ -197,11 +139,6 @@ static void uwsgi_offload_close(struct uwsgi_thread *ut, struct uwsgi_offload_re
uwsgi_buffer_destroy(uor->ubuf);
}
if (uor->pipe[0] != -1) {
close(uor->pipe[1]);
close(uor->pipe[0]);
}
free(uor);
}
@@ -222,7 +159,7 @@ static void uwsgi_offload_append(struct uwsgi_thread *ut, struct uwsgi_offload_r
static struct uwsgi_offload_request *uwsgi_offload_get_by_fd(struct uwsgi_thread *ut, int s) {
struct uwsgi_offload_request *uor = ut->offload_requests_head;
while (uor) {
if (uor->s == s || uor->fd == s || uor->fd2 == s) {
if (uor->s == s || uor->fd == s) {
return uor;
}
uor = uor->next;
@@ -248,8 +185,8 @@ static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
free(uor);
continue;
}
// cal the event function for the first time
if (uor->engine->event_func(ut, uor, -1)) {
// start monitoring socket for write
if (uor->func(ut, uor, -1)) {
uwsgi_offload_close(ut, uor);
continue;
}
@@ -262,7 +199,7 @@ static void uwsgi_offload_loop(struct uwsgi_thread *ut) {
if (!uor)
continue;
// run the hook
if (uor->engine->event_func(ut, uor, interesting_fd)) {
if (uor->func(ut, uor, interesting_fd)) {
uwsgi_offload_close(ut, uor);
}
}
@@ -273,39 +210,6 @@ struct uwsgi_thread *uwsgi_offload_thread_start() {
return uwsgi_thread_new(uwsgi_offload_loop);
}
/*
offload memory transfer
uor->len -> the size of the memory chunk
uor->buf -> the memory to transfer
uor->written -> written bytes
status: none
*/
static int u_offload_memory_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
if (fd == -1) {
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
return 0;
}
ssize_t rlen = write(uor->s, uor->buf + uor->written, uor->len - uor->written);
if (rlen > 0) {
uor->written += rlen;
if (uor->written >= uor->len) {
return -1;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_memory_do()");
}
return -1;
}
/*
the offload task starts after having acquired the file fd
@@ -317,14 +221,14 @@ the offload task starts after having acquired the file fd
*/
static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
static int uwsgi_offload_sendfile_transfer(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
if (fd == -1) {
if (event_queue_add_fd_write(ut->queue, uor->fd2)) return -1;
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
return 0;
}
#if defined(__linux__) || defined(__sun__) || defined(__GNU_kFreeBSD__)
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
#if defined(__linux__) || defined(__sun__)
ssize_t len = sendfile(uor->s, uor->fd, &uor->pos, 128 * 1024);
if (len > 0) {
uor->written += len;
if (uor->written >= uor->len) {
@@ -334,96 +238,31 @@ static int u_offload_sendfile_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
}
else if (len < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_sendfile_do()");
uwsgi_error("sendfile()");
}
#elif defined(__FreeBSD__) || defined(__DragonFly__)
off_t sbytes = 0;
int ret = sendfile(uor->fd, uor->fd2, uor->pos, 0, NULL, &sbytes, 0);
int ret = sendfile(uor->fd, uor->s, uor->pos, 0, NULL, &sbytes, 0);
// transfer finished
if (ret == -1) {
uor->pos += sbytes;
uwsgi_offload_retry
uwsgi_error("u_offload_sendfile_do()");
uwsgi_error("sendfile()");
}
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
#elif defined(__APPLE__)
off_t len = 0;
int ret = sendfile(uor->fd, uor->fd2, uor->pos, &len, NULL, 0);
int ret = sendfile(uor->fd, uor->s, uor->pos, &len, NULL, 0);
// transfer finished
if (ret == -1) {
uor->pos += len;
uwsgi_offload_retry
uwsgi_error("u_offload_sendfile_do()");
uwsgi_error("sendfile()");
}
#endif
return -1;
}
/*
pipe offloading
status:
0 -> waiting for data on fd
1 -> waiting for write to s
*/
static int u_offload_pipe_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
ssize_t rlen;
// setup
if (fd == -1) {
event_queue_add_fd_read(ut->queue, uor->fd);
return 0;
}
switch(uor->status) {
// read event from fd
case 0:
if (!uor->buf) {
uor->buf = uwsgi_malloc(4096);
}
rlen = read(uor->fd, uor->buf, 4096);
if (rlen > 0) {
uor->to_write = rlen;
uor->pos = 0;
if (event_queue_del_fd(ut->queue, uor->fd, event_queue_read())) return -1;
if (event_queue_add_fd_write(ut->queue, uor->s)) return -1;
uor->status = 1;
return 0;
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_pipe_do() -> read()");
}
return -1;
// write event on s
case 1:
rlen = write(uor->s, uor->buf + uor->pos, uor->to_write);
if (rlen > 0) {
uor->to_write -= rlen;
uor->pos += rlen;
if (uor->to_write == 0) {
if (event_queue_del_fd(ut->queue, uor->s, event_queue_write())) return -1;
if (event_queue_add_fd_read(ut->queue, uor->fd)) return -1;
uor->status = 0;
}
return 0;
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_pipe_do() -> write()");
}
return -1;
default:
break;
}
return -1;
}
/*
the offload task starts soon after the call to connect()
@@ -434,7 +273,7 @@ the offload task starts soon after the call to connect()
3 -> write to s
4 -> write to fd
*/
static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
static int uwsgi_offload_net_transfer(struct uwsgi_thread *ut, struct uwsgi_offload_request *uor, int fd) {
ssize_t rlen;
@@ -450,7 +289,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
if (fd == uor->fd) {
uor->status = 1;
// ok try to send the request right now...
return u_offload_transfer_do(ut, uor, fd);
return uwsgi_offload_net_transfer(ut, uor, fd);
}
return -1;
// write event (or just connected)
@@ -468,7 +307,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> write()");
uwsgi_error("uwsgi_offload_net_transfer() -> write()");
}
}
return -1;
@@ -488,7 +327,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> read()/fd");
uwsgi_error("uwsgi_offload_net_transfer() -> read()/fd");
}
}
else if (fd == uor->s) {
@@ -502,7 +341,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
}
if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> read()/s");
uwsgi_error("uwsgi_offload_net_transfer() -> read()/s");
}
}
return -1;
@@ -521,7 +360,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> write()/s");
uwsgi_error("uwsgi_offload_net_transfer() -> write()/s");
}
return -1;
// write event on fd
@@ -539,7 +378,7 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
}
else if (rlen < 0) {
uwsgi_offload_retry
uwsgi_error("u_offload_transfer_do() -> write()/fd");
uwsgi_error("uwsgi_offload_net_transfer() -> write()/fd");
}
return -1;
default:
@@ -548,111 +387,3 @@ static int u_offload_transfer_do(struct uwsgi_thread *ut, struct uwsgi_offload_r
return -1;
}
int uwsgi_offload_run(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor, int *wait) {
if (uor->engine->prepare_func(wsgi_req, uor)) {
return -1;
}
if (wait) {
if (pipe(uor->pipe)) {
uwsgi_error("uwsgi_offload_setup()/pipe()");
return -1;
}
*wait = uor->pipe[0];
uwsgi_socket_nb(uor->pipe[0]);
uwsgi_socket_nb(uor->pipe[1]);
}
if (uor->takeover) {
wsgi_req->fd_closed = 1;
}
if (uwsgi_offload_enqueue(wsgi_req, uor)) {
close(uor->pipe[0]);
close(uor->pipe[1]);
if (uor->takeover) {
wsgi_req->fd_closed = 0;
}
return -1;
}
return 0;
};
struct uwsgi_offload_engine *uwsgi_offload_engine_by_name(char *name) {
struct uwsgi_offload_engine *uoe = uwsgi.offload_engines;
while(uoe) {
if (!strcmp(name, uoe->name)) {
return uoe;
}
}
return NULL;
}
struct uwsgi_offload_engine *uwsgi_offload_register_engine(char *name, int (*prepare_func)(struct wsgi_request *, struct uwsgi_offload_request *), int (*event_func) (struct uwsgi_thread *, struct uwsgi_offload_request *, int)) {
struct uwsgi_offload_engine *old_engine=NULL,*engine=uwsgi.offload_engines;
while(engine) {
if (!strcmp(engine->name, name)) {
return engine;
}
old_engine = engine;
engine = engine->next;
}
engine = uwsgi_calloc(sizeof(struct uwsgi_offload_engine));
engine->name = name;
engine->prepare_func = prepare_func;
engine->event_func = event_func;
if (old_engine) {
old_engine->next = engine;
}
else {
uwsgi.offload_engines = engine;
}
return engine;
}
void uwsgi_offload_engines_register_all() {
uwsgi.offload_engine_sendfile = uwsgi_offload_register_engine("sendfile", u_offload_sendfile_prepare, u_offload_sendfile_do);
uwsgi.offload_engine_transfer = uwsgi_offload_register_engine("transfer", u_offload_transfer_prepare, u_offload_transfer_do);
uwsgi.offload_engine_memory = uwsgi_offload_register_engine("memory", u_offload_memory_prepare, u_offload_memory_do);
uwsgi.offload_engine_pipe = uwsgi_offload_register_engine("pipe", u_offload_pipe_prepare, u_offload_pipe_do);
}
int uwsgi_offload_request_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_sendfile, &uor, wsgi_req, 1);
uor.fd = fd;
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_net_do(struct wsgi_request *wsgi_req, char *socketname, struct uwsgi_buffer *ubuf) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_transfer, &uor, wsgi_req, 1);
uor.name = socketname;
uor.ubuf = ubuf;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_memory_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_memory, &uor, wsgi_req, 1);
uor.buf = buf;
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
int uwsgi_offload_request_pipe_do(struct wsgi_request *wsgi_req, int fd, size_t len) {
struct uwsgi_offload_request uor;
uwsgi_offload_setup(uwsgi.offload_engine_pipe, &uor, wsgi_req, 1);
uor.fd = fd;
uor.len = len;
return uwsgi_offload_run(wsgi_req, &uor, NULL);
}
+9 -29
View File
@@ -14,9 +14,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
if (equal) {
*equal = 0;
if (!strcmp(p, "requires")) {
if (!plugin_already_loaded(equal+1)) {
uwsgi_load_plugin(-1, equal + 1, NULL);
}
uwsgi_load_plugin(-1, equal + 1, NULL);
}
}
p = strtok_r(NULL, "\n", &ctx);
@@ -26,7 +24,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
}
#endif
struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
static int plugin_already_loaded(const char *plugin) {
int i;
for (i = 0; i < 256; i++) {
@@ -35,7 +33,7 @@ struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return uwsgi.p[i];
return 1;
}
}
if (uwsgi.p[i]->alias) {
@@ -43,7 +41,7 @@ struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return uwsgi.p[i];
return 1;
}
}
}
@@ -55,7 +53,7 @@ struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return uwsgi.p[i];
return 1;
}
}
if (uwsgi.gp[i]->alias) {
@@ -63,21 +61,14 @@ struct uwsgi_plugin *uwsgi_plugin_get(const char *plugin) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return uwsgi.p[i];
return 1;
}
}
}
return NULL;
}
int plugin_already_loaded(const char *plugin) {
struct uwsgi_plugin *up = uwsgi_plugin_get(plugin);
if (up) return 1;
return 0;
}
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
void *plugin_handle = NULL;
@@ -85,8 +76,8 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
char *plugin_filename = NULL;
int need_free = 0;
char *plugin_name = uwsgi_strip(uwsgi_str(plugin));
char *plugin_symbol_name_start = plugin_name;
char *plugin_name = plugin;
char *plugin_symbol_name_start = plugin;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
@@ -100,12 +91,6 @@ void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
colon[0] = ':';
}
char *init_func = strchr(plugin_name, '|');
if (init_func) {
init_func[0] = 0;
init_func++;
}
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
need_free = 1;
@@ -165,12 +150,6 @@ success:
uwsgi_log("!!! UNABLE to load uWSGI plugin: %s !!!\n", dlerror());
}
else {
if (init_func) {
void (*plugin_init_func)() = dlsym(plugin_handle, init_func);
if (plugin_init_func) {
plugin_init_func();
}
}
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start) - 3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
if (!up) {
@@ -186,6 +165,7 @@ success:
uwsgi_log("%s\n", linkpath);
#endif
free(plugin_entry_symbol);
up = dlsym(plugin_handle, plugin_entry_symbol);
char *slash = uwsgi_get_last_char(linkpath, '/');
if (!slash) {
slash = linkpath;
-107
View File
@@ -1,107 +0,0 @@
#include <uwsgi.h>
/*
upload progress facilities
*/
extern struct uwsgi_server uwsgi;
char *uwsgi_upload_progress_create(struct wsgi_request *wsgi_req, int *fd) {
const char *x_progress_id = "X-Progress-ID=";
char *xpi_ptr = (char *) x_progress_id;
uint16_t i;
char *upload_progress_filename = NULL;
if (wsgi_req->uri_len <= 51)
return NULL;
for (i = 0; i < wsgi_req->uri_len; i++) {
if (wsgi_req->uri[i] == xpi_ptr[0]) {
if (xpi_ptr[0] == '=') {
if (wsgi_req->uri + i + 36 <= wsgi_req->uri + wsgi_req->uri_len) {
upload_progress_filename = wsgi_req->uri + i + 1;
}
break;
}
xpi_ptr++;
}
else {
xpi_ptr = (char *) x_progress_id;
}
}
// now check for valid uuid (from spec available at http://en.wikipedia.org/wiki/Universally_unique_identifier)
if (!upload_progress_filename)
return NULL;
uwsgi_log("upload progress uuid = %.*s\n", 36, upload_progress_filename);
if (!check_hex(upload_progress_filename, 8))
return NULL;
if (upload_progress_filename[8] != '-')
return NULL;
if (!check_hex(upload_progress_filename + 9, 4))
return NULL;
if (upload_progress_filename[13] != '-')
return NULL;
if (!check_hex(upload_progress_filename + 14, 4))
return NULL;
if (upload_progress_filename[18] != '-')
return NULL;
if (!check_hex(upload_progress_filename + 19, 4))
return NULL;
if (upload_progress_filename[23] != '-')
return NULL;
if (!check_hex(upload_progress_filename + 24, 12))
return NULL;
upload_progress_filename = uwsgi_concat4n(uwsgi.upload_progress, strlen(uwsgi.upload_progress), "/", 1, upload_progress_filename, 36, ".js", 3);
// here we use O_EXCL to avoid eventual application bug in uuid generation/using
*fd = open(upload_progress_filename, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP);
if (*fd < 0) {
uwsgi_error_open(upload_progress_filename);
free(upload_progress_filename);
return NULL;
}
return upload_progress_filename;
}
int uwsgi_upload_progress_update(struct wsgi_request *wsgi_req, int fd, size_t remains) {
char buf[4096];
int ret = snprintf(buf, 4096, "{ \"state\" : \"uploading\", \"received\" : %llu, \"size\" : %llu }\r\n", (unsigned long long) (wsgi_req->post_cl - remains), (unsigned long long) wsgi_req->post_cl);
if (ret < 0) {
return -1;
}
if (lseek(fd, 0, SEEK_SET)) {
uwsgi_error("uwsgi_upload_progress_update()/lseek()");
return -1;
}
if (write(fd, buf, ret) != ret) {
uwsgi_error("uwsgi_upload_progress_update()/write()");
return -1;
}
if (fsync(fd)) {
uwsgi_error("uwsgi_upload_progress_update()/fsync()");
return -1;
}
return 0;
}
void uwsgi_upload_progress_destroy(char *filename, int fd) {
close(fd);
if (unlink(filename)) {
uwsgi_error("uwsgi_upload_progress_destroy()/unlink()");
}
free(filename);
}
+1417 -526
View File
File diff suppressed because it is too large Load Diff
-57
View File
@@ -1,57 +0,0 @@
#include <uwsgi.h>
/*
QUERY_STRING management functions (mainly used by the internal routing subsystem)
*/
static char *check_qs(char *qs, uint16_t qs_len, char *key, uint16_t keylen, uint16_t *vallen) {
// search for the equal sign
char *equal = memchr(qs, '=', qs_len);
if (!equal) return NULL;
if (uwsgi_strncmp(key, keylen, qs, equal-qs)) {
return NULL;
}
qs_len -= (equal-qs)+1;
if (qs_len == 0) return NULL;
*vallen = qs_len;
return equal+1;
}
char *uwsgi_get_qs(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *vallen) {
uint16_t i;
char *qs = wsgi_req->query_string;
uint16_t qs_len = 0;
char *ptr = wsgi_req->query_string;
//start splitting by ;
for(i=0;i<wsgi_req->query_string_len;i++) {
if (!qs) {
qs = ptr + i;
}
if (ptr[i] == '&') {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
qs_len = 0;
qs = NULL;
}
else {
qs_len++;
}
}
if (qs_len > 0) {
char *value = check_qs(qs, qs_len, key, keylen, vallen);
if (value) {
return value;
}
}
return NULL;
}
+2 -3
View File
@@ -47,7 +47,6 @@ void uwsgi_init_queue() {
// fix header
uwsgi.queue_header = uwsgi.queue;
uwsgi.queue += 16;
close(queue_fd);
}
else {
uwsgi.queue = mmap(NULL, (uwsgi.queue_blocksize * uwsgi.queue_size) + 16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
@@ -57,7 +56,7 @@ void uwsgi_init_queue() {
uwsgi.queue_header->pos = 0;
uwsgi.queue_header->pull_pos = 0;
}
if (uwsgi.queue == MAP_FAILED) {
if (!uwsgi.queue) {
uwsgi_error("mmap()");
exit(1);
}
@@ -66,7 +65,7 @@ void uwsgi_init_queue() {
uwsgi.queue_lock = uwsgi_rwlock_init("queue");
uwsgi_log("*** Queue subsystem initialized: %luMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
uwsgi_log("*** Queue subsystem initialized: %dMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
}
char *uwsgi_queue_get(uint64_t index, uint64_t * size) {
-574
View File
@@ -1,574 +0,0 @@
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
int uwsgi_simple_wait_read_hook(int fd, int timeout) {
struct pollfd upoll;
timeout = timeout * 1000;
upoll.fd = fd;
upoll.events = POLLIN;
upoll.revents = 0;
int ret = poll(&upoll, 1, timeout);
if (ret > 0) {
if (upoll.revents & POLLIN) {
return 1;
}
return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_simple_wait_read_hook()/poll()");
}
return ret;
}
/*
seek()/rewind() language-independent implementations.
*/
void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
if (wsgi_req->post_file) {
if (pos < 0) {
if (fseek(wsgi_req->post_file, pos, SEEK_CUR)) {
uwsgi_error("uwsgi_request_body_seek()/fseek()");
}
wsgi_req->post_pos = ftell(wsgi_req->post_file);
return;
}
if (fseek(wsgi_req->post_file, pos, SEEK_SET)) {
uwsgi_error("uwsgi_request_body_seek()/fseek()");
}
wsgi_req->post_pos = ftell(wsgi_req->post_file);
return;
}
if (uwsgi.post_buffering) {
if (pos < 0) {
if ((off_t) wsgi_req->post_pos - pos < 0) {
wsgi_req->post_pos = 0;
return;
}
wsgi_req->post_pos -= pos;
return;
}
if (pos >= (off_t) uwsgi.post_buffering) {
pos = uwsgi.post_buffering - 1;
}
wsgi_req->post_pos = pos;
}
}
/*
read() and readline() language-independent implementations.
*/
#define uwsgi_read_error0(x) uwsgi_log("[uwsgi-body-read] Error reading %llu bytes. Content-Length: %llu consumed: %llu left: %llu message: Client closed connection\n",\
(unsigned long long) x,\
(unsigned long long) wsgi_req->post_cl, (unsigned long long) wsgi_req->post_pos, (unsigned long long) wsgi_req->post_cl-wsgi_req->post_pos);
#define uwsgi_read_error(x) uwsgi_log("[uwsgi-body-read] Error reading %llu bytes. Content-Length: %llu consumed: %llu left: %llu message: %s\n",\
(unsigned long long) x,\
(unsigned long long) wsgi_req->post_cl, (unsigned long long) wsgi_req->post_pos, (unsigned long long) wsgi_req->post_cl-wsgi_req->post_pos,\
strerror(errno));
#define uwsgi_read_timeout(x) uwsgi_log("[uwsgi-body-read] Timeout reading %llu bytes. Content-Length: %llu consumed: %llu left: %llu\n",\
(unsigned long long) x,\
(unsigned long long) wsgi_req->post_cl, (unsigned long long) wsgi_req->post_pos, (unsigned long long) wsgi_req->post_cl-wsgi_req->post_pos);
static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
size_t remains = UMIN(uwsgi.buffer_size, wsgi_req->post_cl - wsgi_req->post_pos);
int ret;
// allocate more memory if needed
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark == 0) {
memcpy(wsgi_req->post_readline_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos);
wsgi_req->post_readline_watermark -= wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos = 0;
// still something to use ?
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark < remains) {
char *tmp_buf = realloc(wsgi_req->post_readline_buf, wsgi_req->post_readline_size + remains);
if (!tmp_buf) {
uwsgi_error("consume_body_for_readline()/realloc()");
return -1;
}
wsgi_req->post_readline_buf = tmp_buf;
wsgi_req->post_readline_size += remains;
// INFORM THE USER HIS readline() USAGE IS FOOLISH
if (!wsgi_req->post_warning && wsgi_req->post_readline_size > (uwsgi.body_read_warning * 1024*1024)) {
uwsgi_log("[uwsgi-warning] you are using readline() on request body allocating over than %llu MB, that is really bad and can be avoided...\n", (unsigned long long) (wsgi_req->post_readline_size/(1024*1024)));
wsgi_req->post_warning = 1;
}
}
}
remains = UMIN(wsgi_req->post_readline_size - wsgi_req->post_readline_watermark, wsgi_req->post_cl - wsgi_req->post_pos);
// read from a file
if (wsgi_req->post_file) {
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
if (ret == 0) {
uwsgi_error("consume_body_for_readline()/fread()");
return -1;
}
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from post_buffering memory
if (uwsgi.post_buffering) {
memcpy(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, wsgi_req->post_buffering_buf + wsgi_req->post_pos, remains);
wsgi_req->post_pos += remains;
wsgi_req->post_readline_watermark += remains;
return 0;
}
// read from socket
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
if (len == 0) {
uwsgi_read_error(remains);
return -1;
}
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
uwsgi_read_error(remains);
return -1;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark , remains);
if (len > 0) {
wsgi_req->post_pos += len;
wsgi_req->post_readline_watermark += len;
return 0;
}
uwsgi_read_error(remains);
return -1;
}
// 0 means timeout
else if (ret == 0) {
uwsgi_read_timeout(remains);
return -1;
}
uwsgi_read_error(remains);
return -1;
}
// TODO take hint into account
// readline_buf is allocated when needed and freed at the end of the request
char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, ssize_t *rlen) {
// return 0 if no post_cl or pos >= post_cl and no residual data
if ((!wsgi_req->post_cl || wsgi_req->post_pos >= wsgi_req->post_cl ) && !wsgi_req->post_readline_pos) {
return uwsgi.empty;
}
// some residual data ?
if (wsgi_req->post_readline_pos > 0) {
size_t i;
for(i=wsgi_req->post_readline_pos;i<wsgi_req->post_readline_watermark;i++) {
// found a newline
if (wsgi_req->post_readline_buf[i] == '\n') {
*rlen = (i+1)-wsgi_req->post_readline_pos;
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos += *rlen;
// all the readline buffer has been consumed
if (wsgi_req->post_readline_pos >= wsgi_req->post_readline_watermark) {
wsgi_req->post_readline_pos = 0;
wsgi_req->post_readline_watermark = 0;
}
return buf;
}
}
// ok, no newline found, continue below
}
// allocate memory on the first round
if (!wsgi_req->post_readline_buf) {
size_t amount = UMIN(uwsgi.buffer_size, wsgi_req->post_cl);
wsgi_req->post_readline_buf = malloc(amount);
if (!wsgi_req->post_readline_buf) {
uwsgi_error("uwsgi_request_body_readline()/malloc()");
*rlen = -1;
return NULL;
}
wsgi_req->post_readline_size = amount;
}
// ok, no newline found, consume a bit more of memory and retry
for(;;) {
// no more data to consume
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
if (consume_body_for_readline(wsgi_req)) {
*rlen = -1;
return NULL;
}
size_t i;
for(i=wsgi_req->post_readline_pos;i<wsgi_req->post_readline_watermark;i++) {
if (wsgi_req->post_readline_buf[i] == '\n') {
*rlen = (i+1)-wsgi_req->post_readline_pos;
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos += *rlen;
if (wsgi_req->post_readline_pos >= wsgi_req->post_readline_watermark) {
wsgi_req->post_readline_pos = 0;
wsgi_req->post_readline_watermark = 0;
}
return buf;
}
}
}
// no line found, let's return all
*rlen = wsgi_req->post_readline_size - wsgi_req->post_readline_pos;
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos = 0;
return buf;
}
char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize_t *rlen) {
int ret = -1;
size_t remains = hint;
// return empty if no post_cl or pos >= post_cl and no residual data
if ((!wsgi_req->post_cl || wsgi_req->post_pos >= wsgi_req->post_cl ) && !wsgi_req->post_readline_pos) {
return uwsgi.empty;
}
// return the whole input
if (remains <= 0) {
remains = wsgi_req->post_cl;
}
// some residual data ?
if (wsgi_req->post_readline_pos > 0) {
if (remains <= (wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos)) {
*rlen = remains;
char *buf = wsgi_req->post_readline_buf + wsgi_req->post_readline_pos;
wsgi_req->post_readline_pos += remains;
return buf;
}
// the hint is higher than residual data, let's copy it to read() memory and go on
size_t avail = wsgi_req->post_readline_watermark - wsgi_req->post_readline_pos;
// check if we have enough memory...
if (avail > wsgi_req->post_read_buf_size) {
char *tmp_buf = realloc(wsgi_req->post_read_buf, avail);
if (!tmp_buf) {
uwsgi_error("uwsgi_request_body_read()/realloc()");
*rlen = -1;
return NULL;
}
wsgi_req->post_read_buf = tmp_buf;
wsgi_req->post_read_buf_size = avail;
if (!wsgi_req->post_warning && wsgi_req->post_read_buf_size > (uwsgi.body_read_warning * 1024*1024)) {
uwsgi_log("[uwsgi-warning] you are using read() on request body allocating over than %llu MB, that is really bad and can be avoided...\n", (unsigned long long) (wsgi_req->post_read_buf_size/(1024*1024)));
wsgi_req->post_warning = 1;
}
}
// fix remains...
if (remains > 0) {
remains -= avail;
}
*rlen += avail;
memcpy(wsgi_req->post_read_buf, wsgi_req->post_readline_buf + wsgi_req->post_readline_pos, avail);
wsgi_req->post_readline_pos = 0;
wsgi_req->post_readline_watermark = 0;
}
if (remains + wsgi_req->post_pos > wsgi_req->post_cl) {
remains = wsgi_req->post_cl - wsgi_req->post_pos;
}
if (remains == 0) {
if (*rlen > 0) {
return wsgi_req->post_read_buf;
}
else {
return uwsgi.empty;
}
}
// read from post buffering memory
if (uwsgi.post_buffering > 0 && !wsgi_req->post_file) {
*rlen += remains;
char *buf = wsgi_req->post_buffering_buf+wsgi_req->post_pos;
wsgi_req->post_pos += remains;
return buf;
}
// ok we need to check if we need to allocate memory
if (!wsgi_req->post_read_buf) {
wsgi_req->post_read_buf = malloc(remains);
if (!wsgi_req->post_read_buf) {
uwsgi_error("uwsgi_request_body_read()/malloc()");
*rlen = -1;
return NULL;
}
wsgi_req->post_read_buf_size = remains;
}
// need to realloc ?
else {
if ((remains+*rlen) > wsgi_req->post_read_buf_size) {
char *tmp_buf = realloc(wsgi_req->post_read_buf, (remains+*rlen));
if (!tmp_buf) {
uwsgi_error("uwsgi_request_body_read()/realloc()");
*rlen = -1;
return NULL;
}
wsgi_req->post_read_buf = tmp_buf;
wsgi_req->post_read_buf_size = (remains+*rlen);
if (!wsgi_req->post_warning && wsgi_req->post_read_buf_size > (uwsgi.body_read_warning * 1024*1024)) {
uwsgi_log("[uwsgi-warning] you are using read() on request body allocating over than %llu MB, that is really bad and can be avoided...\n", (unsigned long long) (wsgi_req->post_read_buf_size/(1024*1024)));
wsgi_req->post_warning = 1;
}
}
}
// check for disk buffered body first (they are all read in one shot)
if (wsgi_req->post_file) {
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
*rlen = -1;
uwsgi_error("uwsgi_request_body_read()/fread()");
return NULL;
}
*rlen += remains;
wsgi_req->post_pos+= remains;
return wsgi_req->post_read_buf;
}
// ok read all the required bytes...
while(remains > 0) {
// here we first try to read (as data could be already available)
ssize_t len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_read_buf + *rlen , remains);
if (len > 0) {
wsgi_req->post_pos+=len;
remains -= len;
*rlen += len;
continue;
}
// client closed connection...
if (len == 0) {
*rlen = -1;
uwsgi_read_error0(remains);
return NULL;
}
if (len < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
*rlen = -1;
uwsgi_read_error(remains);
return NULL;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
len = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_read_buf + *rlen, remains);
if (len > 0) {
wsgi_req->post_pos+=len;
remains -= len;
*rlen += len;
continue;
}else if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
*rlen = -1;
if (len == 0) {
uwsgi_read_error0(remains);
}
else {
uwsgi_read_error(remains);
}
return NULL;
}
// 0 means timeout
else if (ret == 0) {
*rlen = 0;
uwsgi_read_timeout(remains);
return NULL;
}
*rlen = -1;
uwsgi_read_error(remains);
return NULL;
}
return wsgi_req->post_read_buf;
}
/*
post buffering
*/
int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
size_t remains = wsgi_req->post_cl;
int ret;
char *ptr = wsgi_req->post_buffering_buf;
while (remains > 0) {
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
}
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
if (rlen > 0) {
remains -= rlen;
ptr += rlen;
continue;
}
if (rlen == 0) {
uwsgi_read_error0(remains);
return -1;
}
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
uwsgi_read_error(remains);
return -1;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, ptr, remains);
if (rlen > 0) {
remains -= rlen;
ptr += rlen;
continue;
}
}
if (ret < 0) {
uwsgi_read_error(remains);
return -1;
}
uwsgi_read_timeout(remains);
return -1;
}
return 0;
}
int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
size_t post_remains = wsgi_req->post_cl;
int ret;
int upload_progress_fd = -1;
char *upload_progress_filename = NULL;
wsgi_req->post_file = uwsgi_tmpfile();
if (!wsgi_req->post_file) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
return -1;
}
if (uwsgi.upload_progress) {
// first check for X-Progress-ID size
// separator + 'X-Progress-ID' + '=' + uuid
upload_progress_filename = uwsgi_upload_progress_create(wsgi_req, &upload_progress_fd);
if (!upload_progress_filename) {
uwsgi_log("invalid X-Progress-ID value: must be a UUID\n");
}
}
// manage buffered data and upload progress
while (post_remains > 0) {
// during post buffering we need to constantly reset the harakiri
if (uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] > 0) {
inc_harakiri(uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
}
// we use the already available post buffering buffer to read chunks....
size_t remains = UMIN(post_remains, uwsgi.post_buffering);
// first try to read data (there could be something already available
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_buffering_buf, remains);
if (rlen > 0) goto write;
if (rlen == 0) {
uwsgi_read_error0(remains);
goto end;
}
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
goto wait;
}
uwsgi_read_error(remains);
goto end;
}
wait:
ret = uwsgi_wait_read_req(wsgi_req);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->post_buffering_buf, remains);
if (rlen > 0) goto write;
if (rlen == 0) {
uwsgi_read_error0(remains);
}
else {
uwsgi_read_error(remains);
}
goto end;
}
if (ret < 0) {
uwsgi_read_error(remains);
goto end;
}
uwsgi_read_timeout(remains);
goto end;
write:
if (fwrite(wsgi_req->post_buffering_buf, rlen, 1, wsgi_req->post_file) != 1) {
uwsgi_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
goto end;
}
post_remains -= rlen;
if (upload_progress_filename) {
// stop updating it on errors
if (uwsgi_upload_progress_update(wsgi_req, upload_progress_fd, post_remains)) {
uwsgi_upload_progress_destroy(upload_progress_filename, upload_progress_fd);
upload_progress_filename = NULL;
}
}
}
rewind(wsgi_req->post_file);
if (upload_progress_filename) {
uwsgi_upload_progress_destroy(upload_progress_filename, upload_progress_fd);
}
return 0;
end:
if (upload_progress_filename) {
uwsgi_upload_progress_destroy(upload_progress_filename, upload_progress_fd);
}
return -1;
}
+38 -38
View File
@@ -62,49 +62,49 @@ int uwsgi_regexp_ovector(pcre * pattern, pcre_extra * pattern_extra) {
char *uwsgi_regexp_apply_ovec(char *src, int src_n, char *dst, int dst_n, int *ovector, int n) {
int i;
int dollar = 0;
int i;
int dollar = 0;
size_t dollars = n;
for(i=0;i<dst_n;i++) {
if (dst[i] == '$') {
dollars++;
}
}
size_t dollars = n;
char *res = uwsgi_malloc(dst_n + (src_n * dollars) + 1);
char *ptr = res;
for(i=0;i<dst_n;i++) {
if (dst[i] == '$') {
dollars++;
}
}
for (i = 0; i < dst_n; i++) {
if (dollar) {
if (isdigit((int) dst[i])) {
int pos = (dst[i] - 48);
if (pos <= n) {
pos = pos * 2;
memcpy(ptr, src + ovector[pos], ovector[pos + 1] - ovector[pos]);
ptr += ovector[pos + 1] - ovector[pos];
}
}
else {
*ptr++ = '$';
*ptr++ = dst[i];
}
dollar = 0;
}
else {
if (dst[i] == '$') {
dollar = 1;
}
else {
*ptr++ = dst[i];
}
}
}
char *res = uwsgi_malloc(dst_n + (src_n * dollars) + 1);
char *ptr = res;
*ptr++ = 0;
for (i = 0; i < dst_n; i++) {
if (dollar) {
if (isdigit((int) dst[i])) {
int pos = (dst[i] - 48);
if (pos <= n) {
pos = pos * 2;
memcpy(ptr, src + ovector[pos], ovector[pos + 1] - ovector[pos]);
ptr += ovector[pos + 1] - ovector[pos];
}
}
else {
*ptr++ = '$';
*ptr++ = dst[i];
}
dollar = 0;
}
else {
if (dst[i] == '$') {
dollar = 1;
}
else {
*ptr++ = dst[i];
}
}
}
return res;
*ptr++ = 0;
return res;
}
#endif
+74 -1795
View File
File diff suppressed because it is too large Load Diff
+47 -83
View File
@@ -1,57 +1,31 @@
#include <uwsgi.h>
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
int uwsgi_register_rpc(char *name, struct uwsgi_plugin *plugin, uint8_t args, void *func) {
int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func) {
struct uwsgi_rpc *urpc;
int ret = -1;
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
uwsgi_log("only the master and the workers can register RPC functions\n");
if (uwsgi.mywid != 0) {
uwsgi_log("you can register RPC functions only in the master\n");
return -1;
}
uwsgi_lock(uwsgi.rpc_table_lock);
// first check if a function is already registered
size_t i;
for(i=0;i<uwsgi.shared->rpc_count[uwsgi.mywid];i++) {
int pos = (uwsgi.mywid * uwsgi.rpc_max) + i;
urpc = &uwsgi.rpc_table[pos];
if (!strcmp(name, urpc->name)) {
goto already;
}
}
if (uwsgi.shared->rpc_count < MAX_RPC) {
urpc = &uwsgi.shared->rpc_table[uwsgi.shared->rpc_count];
if (uwsgi.shared->rpc_count[uwsgi.mywid] < uwsgi.rpc_max) {
int pos = (uwsgi.mywid * uwsgi.rpc_max) + uwsgi.shared->rpc_count[uwsgi.mywid];
urpc = &uwsgi.rpc_table[pos];
uwsgi.shared->rpc_count[uwsgi.mywid]++;
already:
memcpy(urpc->name, name, strlen(name));
urpc->plugin = plugin;
urpc->modifier1 = modifier1;
urpc->args = args;
urpc->func = func;
urpc->shared = uwsgi.mywid == 0 ? 1 : 0;
uwsgi.shared->rpc_count++;
ret = 0;
if (uwsgi.mywid == 0) {
uwsgi_log("registered shared/inherited RPC function \"%s\"\n", name);
}
else {
uwsgi_log("registered RPC function \"%s\" on worker %d\n", name, uwsgi.mywid);
}
}
// implement cow
if (uwsgi.mywid == 0) {
int i;
for(i=1;i<=uwsgi.numproc;i++) {
uwsgi.shared->rpc_count[i] = uwsgi.shared->rpc_count[0];
int pos = (i * uwsgi.rpc_max);
memcpy(&uwsgi.rpc_table[pos], uwsgi.rpc_table, sizeof(struct uwsgi_rpc) * uwsgi.rpc_max);
}
uwsgi_log("registered RPC function %s\n", name);
}
uwsgi_unlock(uwsgi.rpc_table_lock);
@@ -62,23 +36,21 @@ already:
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
struct uwsgi_rpc *urpc = NULL;
uint64_t i;
int i;
uint16_t ret = 0;
int pos = (uwsgi.mywid * uwsgi.rpc_max);
for (i = 0; i < uwsgi.shared->rpc_count[uwsgi.mywid]; i++) {
if (uwsgi.rpc_table[pos + i].name[0] != 0) {
if (!strcmp(uwsgi.rpc_table[pos + i].name, name)) {
urpc = &uwsgi.rpc_table[pos + i];
for (i = 0; i < uwsgi.shared->rpc_count; i++) {
if (uwsgi.shared->rpc_table[i].name[0] != 0) {
if (!strcmp(uwsgi.shared->rpc_table[i].name, name)) {
urpc = &uwsgi.shared->rpc_table[i];
break;
}
}
}
if (urpc) {
if (urpc->plugin->rpc) {
ret = urpc->plugin->rpc(urpc->func, argc, argv, argvs, output);
if (uwsgi.p[urpc->modifier1]->rpc) {
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
}
}
@@ -90,31 +62,25 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
uint8_t i;
uint16_t ulen;
struct uwsgi_header *uh = NULL;
struct uwsgi_header uh;
char *buffer = NULL;
*len = 0;
if (node == NULL || !strcmp(node, "")) {
// allocate the whole buffer
buffer = uwsgi_malloc(UMAX16);
buffer = uwsgi_malloc(65536);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
return buffer;
}
// connect to node (async way)
int fd = uwsgi_connect(node, 0, 1);
// connect to node
int fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0)
return NULL;
// wait for connection;
int ret = uwsgi.wait_write_hook(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (ret <= 0) {
close(fd);
return NULL;
}
// prepare a uwsgi array
uint16_t buffer_size = 2 + strlen(func);
@@ -123,16 +89,14 @@ char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t
}
// allocate the whole buffer
buffer = uwsgi_malloc(4+buffer_size);
buffer = uwsgi_malloc(65536);
// set the uwsgi header
uh = (struct uwsgi_header *) buffer;
uh->modifier1 = 173;
uh->pktsize = buffer_size;
uh->modifier2 = 0;
uh.modifier1 = 173;
uh.pktsize = buffer_size;
uh.modifier2 = 0;
// add func to the array
char *bufptr = buffer + 4;
char *bufptr = buffer;
ulen = strlen(func);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
@@ -147,33 +111,33 @@ 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
if (uwsgi_write_true_nb(fd, buffer, buffer_size+4, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
goto error;
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
// 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])) {
goto error;
if (write(fd, buffer, buffer_size) != buffer_size) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
if (uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buffer) < 0) {
close(fd);
free(buffer);
return NULL;
}
close(fd);
*len = rlen;
*len = uh.pktsize;
if (*len == 0) {
goto error;
free(buffer);
return NULL;
}
return buffer;
error:
close(fd);
free(buffer);
return NULL;
}
void uwsgi_rpc_init() {
uwsgi.rpc_table = uwsgi_calloc_shared((sizeof(struct uwsgi_rpc) * uwsgi.rpc_max) * (uwsgi.numproc+1));
uwsgi.shared->rpc_count = uwsgi_calloc_shared(sizeof(uint64_t) * (uwsgi.numproc+1));
}
+155 -60
View File
@@ -2,78 +2,173 @@
extern struct uwsgi_server uwsgi;
// sendfile() abstraction
ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
// for platform not supporting sendfile we need to rely on boring read/write
// generally that platforms have very low memory, so use a 8k buffer
char buf[8192];
ssize_t uwsgi_sendfile(struct wsgi_request * wsgi_req) {
if (uwsgi.disable_sendfile) goto no_sendfile;
int fd = wsgi_req->sendfile_fd;
int sockfd = wsgi_req->poll.fd;
struct stat stat_buf;
ssize_t sst = 0;
#if defined(__FreeBSD__) || defined(__DragonFly__)
off_t sf_len = len;
int sf_ret = sendfile(filefd, sockfd, pos, len, NULL, &sf_len, 0);
if (sf_ret == 0 || (sf_ret == -1 && errno == EAGAIN)) return sf_len;
return -1;
#elif defined(__APPLE__) && !defined(NO_SENDFILE)
off_t sf_len = 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__) || defined(__GNU_kFreeBSD__)
off_t off = pos;
return sendfile(sockfd, filefd, &off, len);
#endif
if (!wsgi_req->sendfile_fd_size) {
no_sendfile:
if (pos > 0) {
if (lseek(filefd, pos, SEEK_SET) < 0) {
uwsgi_error("uwsgi_sendfile_do()/seek()");
return -1;
if (fstat(fd, &stat_buf)) {
uwsgi_error("fstat()");
goto end;
}
else {
wsgi_req->sendfile_fd_size = stat_buf.st_size;
}
}
ssize_t rlen = read(filefd, buf, UMIN(len, 8192));
if (rlen <= 0) {
uwsgi_error("uwsgi_sendfile_do()/read()");
return -1;
if (wsgi_req->sendfile_fd_size) {
if (!wsgi_req->sendfile_fd_chunk)
wsgi_req->sendfile_fd_chunk = 4096;
if (wsgi_req->socket->proto_sendfile) {
sst = wsgi_req->socket->proto_sendfile(wsgi_req);
}
else {
sst = uwsgi_do_sendfile(sockfd, wsgi_req->sendfile_fd, wsgi_req->sendfile_fd_size, wsgi_req->sendfile_fd_chunk, &wsgi_req->sendfile_fd_pos, uwsgi.async);
}
}
return write(sockfd, buf, rlen);
end:
return sst;
}
ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk, off_t * pos, int async) {
/*
simple non blocking sendfile implementation
(generally used as fallback)
*/
#if defined(__FreeBSD__) || defined(__DragonFly__)
int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
int sf_ret;
wsgi_req->write_pos = 0;
off_t sf_len = filesize;
for(;;) {
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_simple_sendfile()");
}
wsgi_req->write_errors++;
return -1;
}
if (ret == UWSGI_OK) {
break;
}
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) {
wsgi_req->write_errors++;
return -1;
}
if (ret == 0) {
uwsgi_log("uwsgi_simple_sendfile() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
if (async > 1) {
sf_len = chunk;
sf_ret = sendfile(filefd, sockfd, *pos, 0, NULL, &sf_len, 0);
*pos += sf_len;
}
else {
sf_ret = sendfile(filefd, sockfd, 0, 0, NULL, &sf_len, 0);
}
if (sf_ret < 0) {
if (errno != EAGAIN) {
uwsgi_error("sendfile()");
return 0;
}
}
return sf_len;
#elif defined(__APPLE__)
int sf_ret;
off_t sf_len = filesize;
if (async > 1) {
sf_len = chunk;
sf_ret = sendfile(filefd, sockfd, *pos, &sf_len, NULL, 0);
*pos += sf_len;
}
else {
sf_ret = sendfile(filefd, sockfd, 0, &sf_len, NULL, 0);
}
if (sf_ret) {
#ifdef UWSGI_DEBUG
uwsgi_log("sf_len = %d\n", sf_len);
#endif
uwsgi_error("sendfile()");
return 0;
}
return sf_len;
#elif defined(__linux__) || defined(__sun__)
int sf_ret;
size_t written = 0;
if (async > 1) {
sf_ret = sendfile(sockfd, filefd, pos, chunk);
if (sf_ret < 0) {
uwsgi_error("sendfile()");
return 0;
}
return sf_ret;
}
while (written < filesize) {
sf_ret = sendfile(sockfd, filefd, pos, filesize - written);
if (sf_ret < 0) {
uwsgi_error("sendfile()");
return 0;
}
else if (sf_ret == 0) {
return 0;
}
written += sf_ret;
}
return written;
#else
static size_t nosf_buf_size = 0;
static char *nosf_buf;
char *nosf_buf2;
ssize_t jlen = 0;
ssize_t rlen = 0;
ssize_t i = 0;
if (!nosf_buf) {
nosf_buf = malloc(chunk);
}
else if (chunk != nosf_buf_size) {
nosf_buf2 = realloc(nosf_buf, chunk);
if (!nosf_buf2) {
free(nosf_buf);
}
nosf_buf = nosf_buf2;
}
if (!nosf_buf) {
uwsgi_error("sendfile malloc()/realloc()");
return 0;
}
nosf_buf_size = chunk;
if (async > 1) {
jlen = read(filefd, nosf_buf, chunk);
if (jlen <= 0) {
uwsgi_error("read()");
return 0;
}
jlen = write(sockfd, nosf_buf, jlen);
if (jlen <= 0) {
uwsgi_error("write()");
return 0;
}
return jlen;
}
while (i < (int) filesize) {
jlen = read(filefd, nosf_buf, chunk);
if (jlen <= 0) {
uwsgi_error("read()");
break;
}
i += jlen;
jlen = write(sockfd, nosf_buf, jlen);
if (jlen <= 0) {
uwsgi_error("write()");
break;
}
rlen += jlen;
}
return rlen;
#endif
return 0;
}
+9 -15
View File
@@ -106,14 +106,13 @@ void uwsgi_setup_inherited_sockets() {
//now close all the unbound fd
for (j = 3; j < (int) uwsgi.max_fd; j++) {
int useless = 1;
if (uwsgi_fd_is_safe(j)) continue;
#ifdef UWSGI_MULTICAST
if (j == uwsgi.cluster_fd)
continue;
#endif
if (uwsgi.has_emperor) {
if (j == uwsgi.emperor_fd)
continue;
if (j == uwsgi.emperor_fd_config)
continue;
}
if (uwsgi.shared->worker_log_pipe[0] > -1) {
@@ -126,21 +125,16 @@ void uwsgi_setup_inherited_sockets() {
continue;
}
if (uwsgi.shared->worker_req_log_pipe[0] > -1) {
if (j == uwsgi.shared->worker_req_log_pipe[0])
continue;
}
if (uwsgi.shared->worker_req_log_pipe[1] > -1) {
if (j == uwsgi.shared->worker_req_log_pipe[1])
continue;
}
if (uwsgi.original_log_fd > -1) {
if (j == uwsgi.original_log_fd)
continue;
}
if (uwsgi.cache_server && uwsgi.cache_server_fd != -1) {
if (j == uwsgi.cache_server_fd)
continue;
}
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
int found = 0;
while (ugs) {

Some files were not shown because too many files have changed in this diff Show More