Compare commits

..
106 Commits
Author SHA1 Message Date
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
357 changed files with 21790 additions and 41173 deletions
-6
View File
@@ -1,11 +1,5 @@
*.o
*.py[co]
*.class
*.jar
*~
*.so
/uwsgi
/uwsgibuild.*
/t/ring/target
-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
-1
View File
@@ -21,4 +21,3 @@ Roy Marples
Aarni Koskela
C Anthony Risinger
Stephen Pierce
Mingli Yuan
+679
View File
@@ -0,0 +1,679 @@
*** current ***
* 1.4.1
- fixed typos in corerouter plugins
- fixed offloading when the number of threads is higher than 1
- fixed static_maps for non-existent paths
- fixed uwsgi_connect() on modern Linux systems to reset the socket to blocking mode
*** november 2012 ***
* 1.4
- gevent improvements
- improved http/https router and fastrouter
- Go official support
- a new set of infos are exported to the stats system
- improved systemd support
- log filtering and routing
- improved tracebacker
- offload transfer for static files, and network transfers
- matheval support
- plugins can be written in Obj-C
- smart attach daemon
- added support for PEP 405 virtualenvs
- rawrouter with xclient support
- internal routing plugin for cache
*** semptember 2012 ***
* 1.3
- python tracebacker
- user-governed harakiri
- simplified external plugin development
- Linux namespace mountpoint improvements
- secured subscription system
- merged routers codebase (fastrouter, http, rawrouter)
- https support in the http router
- config report at the end of uWSGI build process
- improved subscription system (multicast and unix socket)
- custom options
- graceful reloads on shared sockets
- configurable log-master buffer size
- extreme-optimizations for the stats subsystem
- redislog and mongodblog plugins
- added python logger
- mongodb and postgres imperial monitors
- implemented psgix.logger and psgix.cleanup
- full rack spec compliance
- preliminary ipv6 support
- gevent graceful reloads
- support for multiple loggers and logformat
- lazy-apps to load apps after fork() but without changing reloading subsystem
- emperor heartbeat subsystem
- cheaper busyness plugin
- pluggable clock sources
- added router_rewrite and router_http plugins
- external spoolers
- support for section:// and fd:// loaders
- alarm subsystem (with curl and xmpp plugins)
*** april 2012 ***
* 1.2 [20120430]
- PyPy support
- Improved gevent support with threads
- Python auto-reload subsystem
- added --spooler-max-tasks
- pthread robust mutexes support in Linux and Solaris
- posix semaphores support in FreeBSD9
- thread-safe ctime() reporting
- interval support in cron subsystem
- improved syslog support
- better management of disconnected clients
- static files serving improvements
- another set of multithreading optimizations
- minor fixes in the Rack plugin
- Upstart socket-activation support
*** march 2012 ***
* 1.1 [20120317]
- new options parser subsystem
- improved php support
- multiple spooler with multiprocessing
- segmentation fault and floating point exceptions manager
- never-swap option
- zergpool plugin
- perl/psgi multiple interpreters support
- deadlock detector
- pluggable cheaper algos
- new internal routing susbsystem
- preliminary support for config logic
- log rotation infrastructure
- support for paste loggers
- threading improvements
- plugins can now mapped to specific modifiers
- <app> tag is deprecated (use mount option)
- report startup time for apps
- reintroduced expat support
- reintroduced remote spooler plugin
- various fastrouter optimizations
- added ruby rvm support
*** december 2011 ***
* 1.0 [20111230]
- adaptive process spawning (--cheaper option)
- new control options --stop, --reload, --suspend, --resume, --pause
- stats framework
- new subscription system
- support for mime types in static file serving
- posix capablities support
- uWSGI mules and farms
- support for multiple --touch-reload options
- new logging subsystem
- new custom locking subsystem
- process name handling
- better (and faster) HTTP parser
- perl and python threading improvements
- new plugins: rrdtool, carbon, cgi, php
- various improvements in the Rack/ruby plugin
- Linux KSM support
- refactored ping and nagios plugins
- support for signals in lazy mode
- optimized static-file serving
- support for linux unshare()
*** august 2011 ***
* 0.9.9 [20110829]
- various spooler improvements
- upload progress optimizations and fixes
- new emperor mode: Tyrant
- allows multiple --ini options
- better binary path detection
- gevent loop engine support
- resolve domain names in socket logging
- snmp fixes and reintroduction of the snmp-api
- fixed grunt mode
- you can specify build profile via env var UWSGI_PROFILE
- reintroduction of string-based multiapp
- new option --emperor-throttle
- improved queue and sharedarea subsystems
- uWSGI can now be built as a shared library
- new api attribute: uwsgi.magic_table
- improved apache2 module
- new option --pyshell
- allow threads in gateways
- fastrouter improvements
- the application list is now shared and exported to the api
- allows setting the thread stack size
- UWSGI_APPID for better multiapp hosting
- better reloading in lazy mode
- native pump support
- various rack fixes
- support for attaching binary data in the executable
- new option --set
- extreme-optimized http protocol parser
- WSGI handler optimizations
*** july 2011 ***
* 0.9.8.3 [20110723]
- implemented uwsgi.SymZipImporter to load embedded zip files
- OSX Lion is officially supported
- fixed xinetd support (example file added in contrib)
- suppot for systemd socket activation
- added --freebind option (Linux only)
* 0.9.8.2 [20110719]
- fixed an ini and yaml parsing bug spotted by Raffaele Colace
- spooler has been extremely improved
- new option --chown-socket
- added uwsgidecorators for elegant uwsgi api access from python
- the rack plugin is now stable
- support for embedding config and generic files in the server binary
- high-performance cache-server
- accept() is now locked on all threads in the same workers
- preliminary implementation of hooks in emperor
- support for C++ in server core
- tcp port auto-bind
- implemented workers, workerN and spooler signal target
- prefork/multithread uwsgi.signal_wait() implementation
- export uwsgi.node in WSGI vars
- new option --import (python plugin)
- support for unlimited number of Linux cgroups
- broodlord mode
*** june 2011 ***
* 0.9.8.1 [20110625]
- the build system has been improved
- various threading fixes
- fix python GIL status after reload
- new option --propagate-touch
- fixed uwsgi.sendfile
- fixed readline() support in wsgi.input
- fixed dynamic touch reload
- new option --logto2
- export %c in config files
- fixed libyaml support
- support passing modifiers in subscription system
- reset random seed in spooler
- subscribe from a list in a text file
- allow binding on port 0 (auto-assignment)
- reset random seed on grunt
- fix vhost mode for empty hostname
- fixed python3+virtualenv support
- tasks are now allowed to chdir() in spooler
- better zeromq+clustering support
- clustering has been refactored
- fixed rpc
- report correct worker id in cheap mode
- fixed a fd-leak in attach-daemon
- use setsid() in attach-daemon
- zerg mode
- added psgix.harakiri
- allows magic vars in sqlite3 config db
- added UWSGI_FASTROUTER_KEY var
- slowdown async-queue-is-full messages
- new option --cron
- --vassals-start-hook and --vassals-stop-hook
- the proxy plugin has been removed
* 0.9.8 [20110605]
- support for --callable in virtualhosting mode
- a NetBSD fix
- abstract unix socket can be prefixed with \0 (nginx-style)
- add /lib to the linker in sun-like systems
- a mercy mode of 5 seconds is enabled by default on SIGINT/SIGQUIT
* 0.9.8-rc4 [20110602]
- fixed REMOTE_ADDR when --protocol=http
- official support for OpenIndiana
- added a welcome.py test script
- new api attribute uwsgi.version_info
- improved the admin plugin
- two new management flag for backlog queue monitoring
- fixed uwsgi_log for bigger loglines
- new option --early-emperor to allows out-of-jail emperors
- emperor can now spawn other emperors (sub-emperors)
- fixed idle mode in single-process
- fixed solaris iovec
*** may 2011 ***
* 0.9.8-rc3 [20110530]
- snapshotting support
- fixed python 3.x spooler
- improvements for grunt processes
- better abstract unix socket
- --log-socket allows logging to generic DGRAM sockets
- a bunch of solaris fixes
- new option --no-fd-passing for fastrouter
- --fastrouter-subscription-slot to set the number of slot in subscription server
- unlimited shared sockets
- fixed netlink compilation
- auto-reconnect on emperor+amqp server disconnection
- various emperor fixes
- unlimited fastrouter sockets
- better cgroup support
- --add-header option allow adding of custom HTTP response headers
- cheap and idle operational modes
* 0.9.8-rc2 [20110521]
- new option --die-on-term
- fixed touch reload
- a couple of optimizations for wsgi.input
- systemd integration
* 0.9.8-rc1 [20110514]
- massive code cleanup and refactoring
- added vassals loyalty concept
- fixed virtualhosting with dynamic virtualenv
- fixed reloading on grand-central-dispatch-enabled OSX
- improved PSGI support with uGreen and async support
- improved Rack support with complete fiber+async in ruby 1.9
- support for JSON config files
- native multi-protocol support (added fastcgi and http)
- Mongrel2 support
- support for templates in vassals
- various threading fixes
- gcc-4.6 support
- support for logging via zeromq
- support for configuration passed via pipe/stdin
- pythonpath entries are now unlimited
- socket entries are unlimited
- pythonpath can be a glob
- lazy mode added
- new language-independent profiling subsystem
- support for configuration stored in a sqlite3 db
- allow workers to survive to syslogd death (when --log-syslog is used)
- fix traceback in Python 3.x
- support for uwsgi signals in threads
- plugin autoloading
- graceful reloading for threads
- new wsgi.input object
- support for alternative allocators (tcmalloc and jemalloc)
*** april 2011 ***
* 0.9.7.2 [20110406]
- new option --touch-reload <file> to reload the stack on <file> modification
--static-map <mountpoint=documentroot> allows to serve static files
- fixed --post-limit management
- disallow empty socket names
- implemented exception_info WSGI support
- new options --reload-on-as <n> and --reload-on-rss <n> allows
to recycle workers when their memory usage is higher than <n> MB
- fixed syslog support (use --log-syslog[=facility] to enable it)
- improved plugin loading system
- added support for RabbitMQ as event dispatcher for the Emperor
- fixed FreeBSD memory report
- PSGI plugin can be compiled without ithreads
- various Emperor fixes
- fixed a regression with setgroups()
- support for shared sockets (used in jails within network namespaces)
*** march 2011 ***
* 0.9.7.1 [20110326]
- fixed python stackless support
- added persistence for queue
- forbid daemonizing in vassal mode
- modifier1 30 is available again
- allow python modules to be mapped/aliased via http
- added --pidfile2 and --logfile-chown
- added UWSGI_CACHE_GET dynamic variable
- 304/If-Modified-Since support for --check-static
- option --check-cache for integrated caching
- option --map-socket to assign specific workers to socket
- fixed unix fd passing on older OSX versions
- fixed post-buffering without pep3333-input
- fixed python threading without uwsgi cores
- support for Linux network namespace
- build with sys.abiflags if necessary
* 0.9.7 [20110317]
- fixed psgi compilation on GNU systems
- improved --pep3333-input
- better error reporting on failed open/fopen
- fixed uGreen
- added greenlet support
- various solaris fixes
- new help system
- updated async support
- fixed uwsgi.cache_get in python
* 0.9.7-rc3 [20110312]
- added support for persistent cache (--cache-store <filename>)
- less verbose file monitoring
- fixed a race condition in emperor startup
- fixed erlang empty list encoding
- improved snmp support
- fixed cache modifier 111 for 3 and 4
- preliminary cpu-affinity support (Linux only)
- fixed ldap support
- auto-configure ldap compilation
- added --allowed-modifiers (allow only a subset of modifiers)
- fixed a bug with getopt_long
* 0.9.7-rc2 [20110309]
- added cron-like interface to signal framework
- improved Linux namespaces support
- fixed multithreading + --max-requests
- added support for reference in configuration files
* 0.9.7-rc1 [20110307]
- export %v in emperor mode
- fixed signal race condition in server reload
- fixed http router post handling bug
- added uwsgi.erlang_register_process in pyerl plugin
- fixed unix socket inherit
- fixed linux namespace support in recent kernel/gcc
- ported threading to python 3.2
- add build date to uWSGI startup info
- do not allow clustering without defining a socket
- kill all the gateways/daemons on startup errors
- fixed vacuum after chdir()
- fixed gateways reload
- re-added support for OpenBSD and NetBSD
- fixed post-buffering in python
- use erlang binary for python string
- fixed memory leak in pyerl plugin
- removed broken log rotation (post-poned)
- fixed no_argument options in ini and yaml parsing
* 0.9.7-beta1 [20110301]
- fully modular re-design
- advanced build system with presets
- threading support
- emperor mode for massive auto-hosting
- caching subsystem
- message queue (even stacked) support
- improved server reloading system
- support for Linux Cgroups and Namespaces
- integrated upload progress
- Clustering infrastructure via multicast, broadcast or subscriptions
- support for attaching/monitoring external apps to the master process
- improved virtualhosting mode
- extremely improved Python support with better usage of multiple interpreters
- improved multiple apps support
- Production ready, evented HTTP router/proxy/load-balancer
- Production ready, evented uwsgi router/proxy/load-balancer
- new Erlang stack
- Internal signal subsystem
- support for RubyOnRails and Rack apps
- A huge series of fixes and optimizations
*** february 2011 ***
* 0.9.6.8 [20110207]
- fixed a bug when using --limit-as
- fixed a erlang buffer initialization
- added --ignore-sigpipe
- added --master-as-root
*** january 2011 ***
* 0.9.6.7 [20110130]
- a huge amount of async optimizations and fixes
- --logdate takes an optional strftime-like value
- follow $PATH on reloading
- uwsgi.core is exported in WSGI env
- uwsgi.log() respect for --logdate
- initial banner respect for --logdate
- fixed --post-buffering
- default listen backlog queue is now 100
- Python 3 support is no more marked as experimental
- Python 3.2 support
- new option --chroot-reload will force a reload of the uWSGI stack after a chroot
- fixed a typo in INI parsing
*** december 2010 ***
* 0.9.6.6 [20101230]
- support for YAML configuration files
- backported python module aliasing from 0.9.7-dev
- better apache2 module (support for SetEnv directive, fixed REQUEST_URI and improved connection handling)
- uwsgi.post_fork_hook implementation (to execute function after fork()) (thanks George Kollias)
- option --gid calls setgroups() after setgid() (thanks Jorge Cardona)
- fixed uGreen compilation (and uGreen is now built by default)
- fixed timeout and thundering herd problem in async modes (many thanks to Test157 for giving us a good async-test-app)
- disable TCP_INFO in older Linux kernels (thanks Bo Shi)
- enable TCP_INFO in FreeBSD (limited usage due to FreeBSD kernel support)
- fixed static virtualhosting mode using xml files (thanks Guido Notari of Link I.T. spa)
- new option --close-on-exec (thanks Jean-Baptiste Quenot)
- use HTTP_HOST var (and fallback to SERVER_NAME) in virtual hosting mode
- fixed a buffer overflow in automatic socket_name allocation (spotted by Riccardo Magliocchetti)
- Official support for Nexenta
*** september 2010 ***
* 0.9.6.5 [20100929]
- PEP 3333 support
- fix --pythonpath with --wsgi-file
- x-wsgiorg.uwsgi.version renamed to uwsgi.version
* 0.9.6.4 [20100925]
- fix a stupid bug in conditional logging backport
* 0.9.6.3 [20100925]
- fix a buffer overflow in .ini parsing (it throws a glibc error on malloc)
- backport of conditional logging from 0.9.7-dev
- backport of backlog queue monitor from 0.9.7-dev (only Linux)
* 0.9.6.2 [20100915]
- fix a regression in virtual hosting mode
- fix pythonpath usage in --ini and --ini-paste
- new uwsgi packet var: UWSGI_CHDIR
* 0.9.6.1 [20100912]
- print the request uri during SIGPIPE or HARAKIRI
- added SIGUSR2 support (it will print the current running request, if available)
- protocol parsing optimization
- fixed --logto support
- new --eval option allows inline definition of WSGI script
- support for defining WSGI script in xml using CDATA
- allow --pp as --pythonpath shortcut
- various spooler optimizations and fixes
- added -O2 optimization by default
- added uwsgi.is_a_reload commodity function
- .ini file support fix
- SNMP agent fix
- support for subprocesses generated by master
- fix a regression in SCRIPT_NAME handling
- Haiku official support
- gcc 2.95 support
- dynamic app management optimizations
- export x-wsgiorg.uwsgi.version in WSGI env
*** august 2010 ***
* 0.9.6 [20100829]
- better handling of SCRIPT_NAME
- vacuum option for deleting unix sockets and pidfiles after usage
- advanced XML configuration
- new configuration systems: INI files and LDAP
- embedded HTTP server for development/testing
- better signal handling
- PSGI plugin improved
- usability fixes and new commodities options for root startup
- grunt processes (detached workers)
- preliminary integrated virtualhosting mode
- new option catch-exceptions can redirect python exceptions to your browser
- logging improvements (--logto and --logdate options)
- Full PEP 333 compliant usage of wsgi.file_wrapper
- re-initialize random seed after every fork() [security fix]
- fix Spooler's usage of stdin
- export WSGI environment in uwsgi.env (for doing evil things)
- logsize tracking (uwsgi.logsize) for future embedded log rotation
*** july 2010 ***
* 0.9.5.4 [20100706]
*** june 2010 ***
* 0.9.5.3 [20100628]
- fixed linux x86_64 compilation (sorry)
* 0.9.5.2 [20100626] *
- fixed a request parsing bug
- applied debian fixes
- fixed multiple interpreter sys.argv
- improved --chmod-socket
- fixed uid 0 SIGHUP
- updated nginx and apache modules
- updated PSGI, lua and example plugin
- fixed --pyargv with python 3.x
- improved plugin build system
*** may 2010 ***
* 0.9.5.1 [20100519] *
- fixed paste support
- added a new modifier (22)
- full support for configuration via environment variables
- nginx_string option in nginx module
- fix for harakiri without master
- backported unladen swallow support for 0.9.6-dev
- fixed address space limit detection via getrlimit()
- http body buffering implementation
- added --prio option (to set priority)
- added --post-limit to limit the size of uploads
- added --logto option to allow udp logging without daemonizing
- applied Gentoo's packagers fixes for build system
* 0.9.5 [20100501] *
- hook based request/modifier management
- plugin support via dlopen
- on-the-fly management flag
- integrated proxy
- logging via udp
- improved spooler for cron-like apps
- async support
- green thread platform (uGreen) on top of the async mode
- transparent Erlang integration
- embedded snmp agent
- nagios mode
- improved python 3.x support
- improved xml configuration
- new build system
- address space usage limiting
- lot of portability fixes
- lot of optimizations and code refactoring
*** april 2010 ***
* Fourth Maintenance release [20100427] *
- backported non-yielding app optimization from 0.9.5
- backported udp logging from 0.9.5
- backported uwsgi_error() from 0.9.5 (no more dumb perror())
- fix a rare (but possible) segmentation fault
- added --version
- updated apache2 module
*** march 2010 ***
* Third Maintenance release [20100310] *
- fix sendfile on 64bit
- include setup.py
*** february 2010 ***
* Maintenance release *
- better support for NetBSD
- threading fix for FreeBSD
- sendfile portability fixes
- new makefiles
- example app for testing static file serving
- fixes for ROCK_SOLID mode
*** january 2010 ***
- Integrated Spooler
- better error management
- long options
- clustering functions
- experimental lighttpd module
- official support for OpenBSD and OpenSolaris
- FastFuncs
- new functions for embedded module
- reliable harakiri
- better Makefiles
- python threads support in master process
- proper timeout handling in apache2 module
- endianess fixes all over the place
- paste support
- Django app for managing and monitoring the uWSGI server
- options for changin uid/gid and chrooting when run by root
- lot of bugfixes and optimizations
*** 20091129 Version 0.9.3 ***
- Nginx 0.7.x module
- configuration via python module
- support (non-standard) for Python 3.x
- Twisted client resource adapter
- graceful restart of worker processes and hot-plug substitution/upgrade of the uWSGI server
- shared memory area to share data between workers/processes
- Tomcat handler
- support for virtualenv
- tons of bugfixes and optimizations
*** 20090829 Version 0.9.2 ***
- TCP support
- configurable internal timeout (socket/poll)
- Cherokee handler
- code refactoring
- Makefiles
- customizable harakiri handler (put an harakiri(environ, start_response) function in your wsgi script)
- limit requests per worker
- a lot of bugfix and optimizations
+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
+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
inherit = base
+14 -1
View File
@@ -1,11 +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
alarm = auto
ipv6 = false
debug = false
unbit = false
xml_implementation = libxml2
@@ -16,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
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
-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
-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
-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
-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 =
-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 = jvm,ring
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
+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
+1 -197
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;
@@ -187,10 +162,8 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
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;
@@ -207,71 +180,12 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
}
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) {
@@ -298,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) {
@@ -351,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))
@@ -382,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) {
@@ -398,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;
@@ -407,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 -187
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,23 +168,8 @@ 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();
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) {
@@ -228,14 +180,14 @@ void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
}
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;
@@ -259,69 +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();
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() {
@@ -331,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);
@@ -358,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("*** WARNING *** 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;
}
}
@@ -384,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();
}
@@ -395,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) {
@@ -413,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++;
@@ -431,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);
}
@@ -450,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
@@ -461,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;
@@ -470,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) {
@@ -479,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 -245
View File
@@ -48,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) {
@@ -121,173 +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_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_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) {
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;
@@ -320,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;
}
+232 -1628
View File
File diff suppressed because it is too large Load Diff
+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;
}
-33
View File
@@ -1,33 +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;
}
-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;
}
}
+18 -110
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) {
@@ -95,13 +70,12 @@ 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 && !ud->pidfile) {
uwsgi_log("daemon \"%s\" (pid: %d) annihilated\n", ud->command, (int) diedpid);
ud->pid = -1;
return -1;
}
ud = ud->next;
@@ -113,15 +87,6 @@ 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) {
uwsgi_spawn_daemon(ud);
return 1;
@@ -168,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) {
@@ -195,6 +146,7 @@ void uwsgi_daemons_spawn_all() {
else {
uwsgi_spawn_daemon(ud);
}
ud->registered = 1;
}
ud = ud->next;
}
@@ -204,29 +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);
while (!kill(ud->pid, 0)) {
kill(-ud->pid, SIGTERM);
sleep(1);
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;
}
}
@@ -234,9 +165,6 @@ 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;
@@ -280,20 +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
devnull = open("/dev/null", O_RDONLY);
if (devnull < 0) {
uwsgi_error("/dev/null open()");
// /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);
}
if (devnull != 0) {
if (dup2(devnull, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(devnull);
}
close(devnull);
}
if (setsid() < 0) {
@@ -333,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);
@@ -366,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;
}
}
@@ -395,9 +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;
#ifdef UWSGI_SSL
uwsgi_ud->legion = legion;
#endif
uwsgi.daemons_cnt++;
+86 -382
View File
@@ -87,7 +87,7 @@ void uwsgi_emperor_blacklist_add(char *id) {
}
}
strncpy(uebi->id, id, 0xff);
strcpy(uebi->id, id);
gettimeofday(&uebi->first_attempt, NULL);
memcpy(&uebi->last_attempt, &uebi->first_attempt, sizeof(struct timeval));
uebi->throttle_level = uwsgi.emperor_throttle;
@@ -122,101 +122,19 @@ void uwsgi_emperor_blacklist_remove(char *id) {
struct uwsgi_emperor_scanner *emperor_scanners;
static int has_extra_extension(char *name) {
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
while(usl) {
if (uwsgi_endswith(name, usl->value)) {
return 1;
}
usl = usl->next;
}
return 0;
}
int uwsgi_emperor_is_valid(char *name) {
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json") || has_extra_extension(name)) {
if (uwsgi_endswith(name, ".xml") || uwsgi_endswith(name, ".ini") || uwsgi_endswith(name, ".yml") || uwsgi_endswith(name, ".yaml") || uwsgi_endswith(name, ".js") || uwsgi_endswith(name, ".json")) {
if (strlen(name) < 0xff) {
return 1;
}
}
return 0;
}
static char *emperor_check_on_demand_socket(char *filename) {
size_t len = 0;
if (uwsgi.emperor_on_demand_extension) {
char *tmp = uwsgi_concat2(filename, uwsgi.emperor_on_demand_extension);
int fd = open(tmp, O_RDONLY);
free(tmp);
if (fd < 0) return NULL;
char *ret = uwsgi_read_fd(fd, &len, 1);
close(fd);
// change the first non prinabel character to 0
size_t i;
for(i=0;i<len;i++) {
if (ret[i] < 32) {
ret[i] = 0;
break;
}
}
if (ret[0] == 0) {
free(ret);
return NULL;
}
return ret;
}
else if (uwsgi.emperor_on_demand_directory) {
// we need to build the socket path automagically
char *start_of_vassal_name = uwsgi_get_last_char(filename, '/');
if (!start_of_vassal_name) {
start_of_vassal_name = filename;
}
else {
start_of_vassal_name++;
}
char *last_dot = uwsgi_get_last_char(filename, '.');
if (!last_dot) return NULL;
return uwsgi_concat4n(uwsgi.emperor_on_demand_directory, strlen(uwsgi.emperor_on_demand_directory), "/", 1, start_of_vassal_name, last_dot - start_of_vassal_name, ".socket", 7);
}
else if (uwsgi.emperor_on_demand_exec) {
int cpipe[2];
if (pipe(cpipe)) {
uwsgi_error("emperor_check_on_demand_socket()pipe()");
return NULL;
}
char *cmd = uwsgi_concat4(uwsgi.emperor_on_demand_exec, " \"", filename, "\"");
int r = uwsgi_run_command(cmd, NULL, cpipe[1]);
free(cmd);
if (r < 0) {
close(cpipe[0]);
close(cpipe[1]);
return NULL;
}
char *ret = uwsgi_read_fd(cpipe[0], &len, 1);
close(cpipe[0]);
close(cpipe[1]);
// change the first non prinabel character to 0
size_t i;
for(i=0;i<len;i++) {
if (ret[i] < 32) {
ret[i] = 0;
break;
}
}
if (ret[0] == 0) {
free(ret);
return NULL;
}
return ret;
}
return NULL;
}
// this is the monitor for non-glob directories
void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
struct uwsgi_instance *ui_current;
@@ -242,27 +160,10 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
ui_current = emperor_get(de->d_name);
uid_t t_uid = st.st_uid;
gid_t t_gid = st.st_gid;
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
struct stat lst;
if (lstat(de->d_name, &lst)) {
uwsgi_error("[emperor-tyrant]/lstat()");
if (ui_current) {
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", de->d_name);
emperor_stop(ui_current);
}
continue;
}
t_uid = lst.st_uid;
t_gid = lst.st_gid;
}
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", de->d_name);
emperor_stop(ui_current);
continue;
@@ -274,9 +175,7 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
}
}
else {
char *socket_name = emperor_check_on_demand_socket(de->d_name);
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
if (socket_name) free(socket_name);
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
closedir(dir);
@@ -286,24 +185,8 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
while (c_ui) {
if (c_ui->scanner == ues) {
if (c_ui->zerg) {
char *colon = strrchr(c_ui->name, ':');
if (!colon) {
emperor_stop(c_ui);
}
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
free(filename);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
c_ui = c_ui->ui_next;
@@ -336,27 +219,10 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
ui_current = emperor_get(g.gl_pathv[i]);
uid_t t_uid = st.st_uid;
gid_t t_gid = st.st_gid;
if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
struct stat lst;
if (lstat(g.gl_pathv[i], &lst)) {
uwsgi_error("[emperor-tyrant]/lstat()");
if (ui_current) {
uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
emperor_stop(ui_current);
}
continue;
}
t_uid = lst.st_uid;
t_gid = lst.st_gid;
}
if (ui_current) {
// check if uid or gid are changed, in such case, stop the instance
if (uwsgi.emperor_tyrant) {
if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
if (st.st_uid != ui_current->uid || st.st_gid != ui_current->gid) {
uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
emperor_stop(ui_current);
continue;
@@ -368,9 +234,7 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
}
}
else {
char *socket_name = emperor_check_on_demand_socket(g.gl_pathv[i]);
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
if (socket_name) free(socket_name);
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
}
}
@@ -381,25 +245,9 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
while (c_ui) {
if (c_ui->scanner == ues) {
if (c_ui->zerg) {
char *colon = strrchr(c_ui->name, ':');
if (!colon) {
emperor_stop(c_ui);
}
else {
char *filename = uwsgi_calloc(0xff);
memcpy(filename, c_ui->name, colon - c_ui->name);
if (stat(filename, &st)) {
emperor_stop(c_ui);
}
free(filename);
}
}
else {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
}
c_ui = c_ui->ui_next;
}
@@ -476,7 +324,7 @@ static void emperor_stats() {
while (c_ui) {
uwsgi_log("vassal instance %s (last modified %lld) status %d loyal %d zerg %d\n", c_ui->name, (long long) c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
uwsgi_log("vassal instance %s (last modified %d) status %d loyal %d zerg %d\n", c_ui->name, c_ui->last_mod, c_ui->status, c_ui->loyal, c_ui->zerg);
c_ui = c_ui->ui_next;
}
@@ -497,22 +345,6 @@ struct uwsgi_instance *emperor_get_by_fd(int fd) {
return NULL;
}
struct uwsgi_instance *emperor_get_by_socket_fd(int fd) {
struct uwsgi_instance *c_ui = ui;
while (c_ui->ui_next) {
c_ui = c_ui->ui_next;
// over engineering...
if (c_ui->on_demand_fd != -1 && c_ui->on_demand_fd == fd) {
return c_ui;
}
}
return NULL;
}
struct uwsgi_instance *emperor_get(char *name) {
@@ -566,10 +398,6 @@ void emperor_del(struct uwsgi_instance *c_ui) {
uwsgi.emperor_broodlord_count--;
}
if (c_ui->socket_name) {
free(c_ui->socket_name);
}
free(c_ui);
}
@@ -588,28 +416,17 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
struct uwsgi_header uh;
// reload the uWSGI instance
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
}
// push the config to the config pipe (if needed)
if (c_ui->use_config) {
uh.modifier1 = 115;
uh.pktsize = c_ui->config_len;
uh.modifier2 = 0;
if (write(c_ui->pipe_config[0], &uh, 4) != 4) {
uwsgi_error("[uwsgi-emperor] write() header config");
if (write(c_ui->pipe[0], "\0", 1) != 1) {
uwsgi_error("write()");
}
else {
if (write(c_ui->pipe_config[0], c_ui->config, c_ui->config_len) != (long) c_ui->config_len) {
uwsgi_error("[uwsgi-emperor] write() config");
}
}
else {
if (write(c_ui->pipe[0], "\1", 1) != 1) {
uwsgi_error("write()");
}
}
c_ui->respawns++;
c_ui->last_mod = mod;
@@ -618,10 +435,17 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
struct uwsgi_instance *c_ui = ui;
struct uwsgi_instance *n_ui = NULL;
pid_t pid;
char **vassal_argv;
char *uef;
char **uenvs;
int counter;
char *colon = NULL;
int i;
struct timeval tv;
#ifdef UWSGI_DEBUG
@@ -629,7 +453,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
#endif
if (strlen(name) > (0xff - 1)) {
uwsgi_log("[emperor] invalid vassal name: %s\n", name);
uwsgi_log("[emperor] invalid vassal name\n", name);
return;
}
@@ -677,7 +501,8 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
c_ui = c_ui->ui_next;
}
n_ui = uwsgi_calloc(sizeof(struct uwsgi_instance));
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
memset(n_ui, 0, sizeof(struct uwsgi_instance));
if (config) {
n_ui->use_config = 1;
@@ -708,60 +533,10 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
n_ui->first_run = uwsgi_now();
n_ui->last_run = n_ui->first_run;
n_ui->on_demand_fd = -1;
if (socket_name) {
n_ui->socket_name = uwsgi_str(socket_name);
}
n_ui->pid = -1;
// ok here we check if we need to bind to the specified socket or continue with the activation
if (socket_name) {
char *tcp_port = strchr(socket_name, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
n_ui->on_demand_fd = bind_to_tcp(socket_name, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
n_ui->on_demand_fd = bind_to_unix(socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
if (n_ui->on_demand_fd < 0) {
uwsgi_error("emperor_add()/bind()");
free(n_ui);
c_ui->ui_next = NULL;
return;
}
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->on_demand_fd);
uwsgi_log("[uwsgi-emperor] %s -> \"on demand\" instance detected, waiting for connections on socket \"%s\" ...\n", name, socket_name);
return;
}
if (uwsgi_emperor_vassal_start(n_ui)) {
// clear the vassal
free(n_ui);
c_ui->ui_next = NULL;
}
}
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
int i;
char *colon = NULL;
int counter;
char **uenvs;
char *uef;
char **vassal_argv;
pid_t pid;
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
uwsgi_error("socketpair()");
return -1;
goto clear;
}
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]);
@@ -769,14 +544,10 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
if (n_ui->use_config) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
uwsgi_error("socketpair()");
return -1;
goto clear;
}
}
if (n_ui->zerg) {
uwsgi.emperor_broodlord_num++;
}
// TODO pre-start hook
// a new uWSGI instance will start
@@ -788,37 +559,23 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
n_ui->pid = pid;
// close the right side of the pipe
close(n_ui->pipe[1]);
// close the "on demand" socket
if (n_ui->on_demand_fd > -1) {
close(n_ui->on_demand_fd);
n_ui->on_demand_fd = -1;
}
if (n_ui->use_config) {
close(n_ui->pipe_config[1]);
}
if (n_ui->use_config) {
struct uwsgi_header uh;
uh.modifier1 = 115;
uh.pktsize = n_ui->config_len;
uh.modifier2 = 0;
if (write(n_ui->pipe_config[0], &uh, 4) != 4) {
uwsgi_error("[uwsgi-emperor] write() header config");
}
else {
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) != (long) n_ui->config_len) {
uwsgi_error("[uwsgi-emperor] write() config");
}
}
if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
uwsgi_error("write()");
}
close(n_ui->pipe_config[0]);
}
return 0;
return;
}
else {
if (uwsgi.emperor_tyrant) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
if (setgid(n_ui->gid)) {
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
if (setgid(gid)) {
uwsgi_error("setgid()");
exit(1);
}
@@ -827,7 +584,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
exit(1);
}
if (setuid(n_ui->uid)) {
if (setuid(uid)) {
uwsgi_error("setuid()");
exit(1);
}
@@ -844,16 +601,6 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
free(uef);
// add UWSGI_BROODLORD_NUM
if (n_ui->zerg) {
uef = uwsgi_num2str(uwsgi.emperor_broodlord_num);
if (setenv("UWSGI_BROODLORD_NUM", uef, 1)) {
uwsgi_error("setenv()");
exit(1);
}
free(uef);
}
if (n_ui->use_config) {
uef = uwsgi_num2str(n_ui->pipe_config[1]);
if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
@@ -865,16 +612,14 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
uenvs = environ;
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13) && strchr(*uenvs, '=')) {
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0), *ne;
if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
if (unsetenv(oe)) {
uwsgi_error("unsetenv()");
free(oe);
break;
}
free(oe);
ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
#ifdef UWSGI_DEBUG
uwsgi_log("putenv %s\n", ne);
#endif
@@ -908,7 +653,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
vassal_argv[0] = uwsgi.binary_path;
if (uwsgi.emperor_broodlord) {
colon = strchr(n_ui->name, ':');
colon = strchr(name, ':');
if (colon) {
colon[0] = 0;
}
@@ -916,43 +661,34 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
// initialize to a default value
vassal_argv[1] = "--inherit";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
if (!strcmp(name + (strlen(name) - 4), ".xml"))
vassal_argv[1] = "--xml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
if (!strcmp(name + (strlen(name) - 4), ".ini"))
vassal_argv[1] = "--ini";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
if (!strcmp(name + (strlen(name) - 4), ".yml"))
vassal_argv[1] = "--yaml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
vassal_argv[1] = "--yaml";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
if (!strcmp(name + (strlen(name) - 3), ".js"))
vassal_argv[1] = "--json";
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
if (!strcmp(name + (strlen(name) - 5), ".json"))
vassal_argv[1] = "--json";
struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
while(usl) {
if (uwsgi_endswith(n_ui->name, usl->value)) {
vassal_argv[1] = "--config";
break;
}
usl = usl->next;
}
if (colon) {
colon[0] = ':';
}
vassal_argv[2] = n_ui->name;
vassal_argv[2] = name;
if (uwsgi.emperor_magic_exec) {
if (!access(n_ui->name, R_OK | X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
if (!access(name, R_OK | X_OK)) {
vassal_argv[2] = uwsgi_concat2("exec://", name);
}
}
if (n_ui->use_config) {
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
vassal_argv[2] = uwsgi_concat2("emperor://", name);
}
counter = 3;
@@ -965,29 +701,18 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
}
vassal_argv[counter] = NULL;
// disable stdin OR map it to the "on demand" socket
if (n_ui->on_demand_fd > -1) {
if (n_ui->on_demand_fd != 0) {
if (dup2(n_ui->on_demand_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(n_ui->on_demand_fd);
}
// disable stdin
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
else {
int stdin_fd = open("/dev/null", O_RDONLY);
if (stdin_fd < 0) {
uwsgi_error_open("/dev/null");
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
close(stdin_fd);
}
close(stdin_fd);
}
// close all of the unneded fd
@@ -1021,7 +746,11 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
exit(UWSGI_EXILE_CODE);
}
return -1;
clear:
free(n_ui);
c_ui->ui_next = NULL;
}
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
@@ -1179,8 +908,6 @@ void emperor_loop() {
char notification_message[64];
struct rlimit rl;
uwsgi.disable_nuclear_blast = 1;
uwsgi.emperor_stats_fd = -1;
if (uwsgi.emperor_pidfile) {
@@ -1262,9 +989,9 @@ void emperor_loop() {
}
// check if a monitor is mapped to that file descriptor
if (uwsgi_emperor_scanner_event(interesting_fd)) {
if (uwsgi_emperor_scanner_event(interesting_fd))
continue;
}
ui_current = emperor_get_by_fd(interesting_fd);
if (ui_current) {
@@ -1272,7 +999,9 @@ void emperor_loop() {
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
emperor_del(ui_current);
if (!ui_current->config_len) {
emperor_del(ui_current);
}
}
else {
if (byte == 17) {
@@ -1293,24 +1022,14 @@ void emperor_loop() {
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
// here we discard socket name as broodlord/zerg cannot be on demand
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
free(zerg_name);
}
}
}
else {
ui_current = emperor_get_by_socket_fd(interesting_fd);
if (ui_current) {
event_queue_del_fd(uwsgi.emperor_queue, ui_current->on_demand_fd, event_queue_read());
if (uwsgi_emperor_vassal_start(ui_current)) {
emperor_del(ui_current);
}
}
else {
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
close(interesting_fd);
}
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
close(interesting_fd);
}
}
@@ -1336,9 +1055,7 @@ void emperor_loop() {
has_children = 0;
while (ui_current->ui_next) {
ui_current = ui_current->ui_next;
if (ui_current->pid > -1) {
has_children++;
}
has_children++;
}
if (uwsgi.notify) {
@@ -1390,7 +1107,7 @@ void emperor_loop() {
}
else {
// UNSAFE
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid, ui_current->socket_name);
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
emperor_del(ui_current);
}
break;
@@ -1484,7 +1201,7 @@ void emperor_send_stats(int fd) {
if (uwsgi_stats_keyval_comma(us, "id", c_ui->name))
goto end0;
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) c_ui->pid))
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) c_ui->pid))
goto end0;
if (uwsgi_stats_keylong_comma(us, "born", (unsigned long long) c_ui->born))
goto end0;
@@ -1503,9 +1220,6 @@ void emperor_send_stats(int fd) {
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
goto end0;
if (uwsgi_stats_keyval_comma(us, "on_demand", c_ui->socket_name ? c_ui->socket_name : ""))
goto end0;
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) c_ui->uid))
goto end0;
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
@@ -1624,7 +1338,6 @@ void uwsgi_emperor_start() {
else {
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
}
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
@@ -1658,7 +1371,7 @@ void uwsgi_check_emperor() {
}
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid, char *socket_name) {
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
if (!uwsgi_emperor_is_valid(name))
return;
@@ -1676,25 +1389,16 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
}
// check if mtime is changed and the uWSGI instance must be reloaded
if (ts > ui_current->last_mod) {
// make a new config (free the old one) if needed
if (config) {
if (ui_current->config)
free(ui_current->config);
ui_current->config = uwsgi_str(config);
ui_current->config_len = strlen(ui_current->config);
}
// reload the instance
// make a new config (free the old one)
free(ui_current->config);
ui_current->config = config;
ui_current->config_len = strlen(config);
// always respawn (no need for amqp-style rules)
emperor_respawn(ui_current, ts);
}
}
else {
// make a copy of the config as it will be freed
char *new_config = NULL;
size_t new_config_len = 0;
if (config) {
new_config = uwsgi_str(config);
new_config_len = strlen(new_config);
}
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
emperor_add(ues, name, ts, uwsgi_str(config), strlen((const char *) config), uid, gid);
}
}
-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);
}
}
+3 -12
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,17 +28,10 @@ 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)
gateway_respawn(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) {
@@ -91,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);
}
+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
+14 -179
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;
@@ -86,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;
@@ -109,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;
@@ -134,41 +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();
#ifdef UWSGI_MULTICAST
uwsgi.multicast_ttl = 1;
#endif
}
void uwsgi_setup_reload() {
@@ -300,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
@@ -311,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)
@@ -322,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)
@@ -345,17 +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.final_routes);
#endif
uwsgi_log("mapped %llu bytes (%llu KB) for %d cores\n", total_memory, total_memory / 1024, uwsgi.cores * uwsgi.numproc);
}
@@ -386,75 +293,3 @@ pid_t uwsgi_daemonize2() {
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);
}
}
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;
}
-1080
View File
File diff suppressed because it is too large Load Diff
+2 -2
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);
+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
-1178
View File
File diff suppressed because it is too large Load Diff
+12 -86
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) {
@@ -529,9 +478,7 @@ void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
memcpy(&semid, uli->lock_ptr, sizeof(int));
retry:
if (semop(semid, &sb, 1)) {
if (errno == EINTR) goto retry;
uwsgi_error("semop()");
}
}
@@ -546,9 +493,7 @@ void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
memcpy(&semid, uli->lock_ptr, sizeof(int));
retry:
if (semop(semid, &sb, 1)) {
if (errno == EINTR) goto retry;
uwsgi_error("semop()");
}
@@ -613,10 +558,6 @@ pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) {
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")) {
@@ -655,13 +596,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)
@@ -679,6 +619,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");
@@ -688,20 +631,11 @@ ready:
if (uwsgi.use_thunder_lock) {
// process shared thunder lock
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
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;
}
@@ -764,18 +698,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;
}
+137 -374
View File
@@ -1,9 +1,9 @@
#ifndef __DragonFly__
#include <uwsgi.h>
#endif
#define _NO_UWSGI_RB
#include "uwsgi.h"
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
#include <sys/user.h>
#include <kvm.h>
#include <sys/user.h>
#elif defined(__sun__)
/* Terrible Hack !!! */
#ifndef _LP64
@@ -17,10 +17,6 @@
#include <sys/sysctl.h>
#endif
#ifdef __DragonFly__
#include <uwsgi.h>
#endif
extern struct uwsgi_server uwsgi;
//use this instead of fprintf to avoid buffering mess with udp logging
@@ -148,21 +144,6 @@ void create_logpipe(void) {
exit(1);
}
if (uwsgi.req_log_master) {
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_req_log_pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_req_log_pipe)) {
#endif
uwsgi_error("socketpair()\n");
exit(1);
}
uwsgi_socket_nb(uwsgi.shared->worker_req_log_pipe[0]);
uwsgi_socket_nb(uwsgi.shared->worker_req_log_pipe[1]);
uwsgi.req_log_fd = uwsgi.shared->worker_req_log_pipe[1];
}
}
#ifdef UWSGI_ZEROMQ
@@ -213,6 +194,7 @@ void logto(char *logfile) {
int fd;
#ifdef UWSGI_UDP
char *udp_port;
struct sockaddr_in udp_addr;
@@ -248,6 +230,7 @@ void logto(char *logfile) {
}
}
else {
#endif
if (uwsgi.log_truncate) {
fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
}
@@ -265,7 +248,9 @@ void logto(char *logfile) {
uwsgi_error("chmod()");
}
}
#ifdef UWSGI_UDP
}
#endif
/* stdout */
@@ -309,70 +294,61 @@ void uwsgi_setup_log() {
}
static struct uwsgi_logger *setup_choosen_logger(struct uwsgi_string_list *usl) {
char *id = NULL;
char *name = usl->value;
char *space = strchr(name, ' ');
if (space) {
int is_id = 1;
int i;
for (i = 0; i < (space - name); i++) {
if (!isalnum((int)name[i])) {
is_id = 0;
break;
}
}
if (is_id) {
id = uwsgi_concat2n(name, space - name, "", 0);
name = space + 1;
}
}
char *colon = strchr(name, ':');
if (colon) {
*colon = 0;
}
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
if (!choosen_logger) {
uwsgi_log("unable to find logger %s\n", name);
exit(1);
}
// make a copy of the logger
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
choosen_logger = copy_of_choosen_logger;
choosen_logger->id = id;
choosen_logger->next = NULL;
if (colon) {
choosen_logger->arg = colon + 1;
// check for empty string
if (*choosen_logger->arg == 0) {
choosen_logger->arg = NULL;
}
*colon = ':';
}
return choosen_logger;
}
void uwsgi_setup_log_master(void) {
struct uwsgi_string_list *usl = uwsgi.requested_logger;
while (usl) {
struct uwsgi_logger *choosen_logger = setup_choosen_logger(usl);
uwsgi_append_logger(choosen_logger);
usl = usl->next;
}
char *id = NULL;
char *name = usl->value;
usl = uwsgi.requested_req_logger;
while (usl) {
struct uwsgi_logger *choosen_logger = setup_choosen_logger(usl);
uwsgi_append_req_logger(choosen_logger);
usl = usl->next;
}
char *space = strchr(name, ' ');
if (space) {
int is_id = 1;
int i;
for (i = 0; i < (space - name); i++) {
if (!isalnum(name[i])) {
is_id = 0;
break;
}
}
if (is_id) {
id = uwsgi_concat2n(name, space - name, "", 0);
name = space + 1;
}
}
char *colon = strchr(name, ':');
if (colon) {
*colon = 0;
}
struct uwsgi_logger *choosen_logger = uwsgi_get_logger(name);
if (!choosen_logger) {
uwsgi_log("unable to find logger %s\n", name);
exit(1);
}
// make a copy of the logger
struct uwsgi_logger *copy_of_choosen_logger = uwsgi_malloc(sizeof(struct uwsgi_logger));
memcpy(copy_of_choosen_logger, choosen_logger, sizeof(struct uwsgi_logger));
choosen_logger = copy_of_choosen_logger;
choosen_logger->id = id;
choosen_logger->next = NULL;
if (colon) {
choosen_logger->arg = colon + 1;
// check for empty string
if (*choosen_logger->arg == 0) {
choosen_logger->arg = NULL;
}
*colon = ':';
}
uwsgi_append_logger(choosen_logger);
usl = usl->next;
}
#ifdef UWSGI_PCRE
// set logger by its id
@@ -381,11 +357,6 @@ void uwsgi_setup_log_master(void) {
url->custom_ptr = uwsgi_get_logger_from_id(url->custom_str);
url = url->next;
}
url = uwsgi.log_req_route;
while (url) {
url->custom_ptr = uwsgi_get_logger_from_id(url->custom_str);
url = url->next;
}
#endif
uwsgi.original_log_fd = dup(1);
@@ -487,13 +458,13 @@ void uwsgi_check_logrotate(void) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
else {
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
else {
uwsgi_error("unable to rotate log: rename()");
@@ -556,7 +527,7 @@ void log_request(struct wsgi_request *wsgi_req) {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_BIG] && (wsgi_req->response_size >= uwsgi.shared->options[UWSGI_OPTION_LOG_BIG])) {
goto logit;
}
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE] && wsgi_req->via == UWSGI_VIA_SENDFILE) {
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE] && (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result)) {
goto logit;
}
@@ -601,19 +572,16 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
}
}
// mark requests via (sendfile, route, offload...)
switch(wsgi_req->via) {
case UWSGI_VIA_SENDFILE:
via = msg1;
break;
case UWSGI_VIA_ROUTE:
via = msg3;
break;
case UWSGI_VIA_OFFLOAD:
via = msg4;
break;
default:
break;
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
via = msg1;
}
// mark route() requests
if (wsgi_req->status == -17) {
via = msg3;
}
else if (wsgi_req->status == -30) {
via = msg4;
}
#ifdef __sun__
@@ -642,21 +610,23 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
}
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
#ifndef UNBIT
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
#else
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
#endif
logvec[logvecpos].iov_base = mempkt;
logvec[logvecpos].iov_len = rlen;
logvecpos++;
}
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %llu %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh->pktsize,
24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %llu %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
// not enough space for logging the request, just log a (safe) minimal message
if (rlen > 4096) {
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] 0.0.0.0 () {%d vars in %d bytes} [%.*s] - - => generated %llu bytes in %llu %s%s(- %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->var_cnt, wsgi_req->uh->pktsize,
24, time_request, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] 0.0.0.0 () {%d vars in %d bytes} [%.*s] - - => generated %llu bytes in %llu %s%s(- %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, (unsigned long long) wsgi_req->response_size, (unsigned long long) rt, tsize, via, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
// argh, last resort, truncate it
if (rlen > 4096) {
rlen = 4096;
@@ -667,17 +637,13 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
logvec[logvecpos].iov_len = rlen;
// do not check for errors
rlen = writev(uwsgi.req_log_fd, logvec, logvecpos + 1);
rlen = writev(2, logvec, logvecpos + 1);
}
void get_memusage(uint64_t * rss, uint64_t * vsz) {
#ifdef UNBIT
uint64_t ret[2];
ret[0] = 0; ret[1] = 0;
syscall(358, ret);
*vsz = ret[0];
*rss = ret[1] * uwsgi.page_size;
*vsz = syscall(356);
#elif defined(__linux__)
FILE *procfile;
int i;
@@ -690,18 +656,6 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
fclose(procfile);
}
*rss = *rss * uwsgi.page_size;
#elif defined(__CYGWIN__)
// same as Linux but rss is not in pages...
FILE *procfile;
int i;
procfile = fopen("/proc/self/stat", "r");
if (procfile) {
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
if (i != 2) {
uwsgi_log("warning: invalid record in /proc/self/stat\n");
}
fclose(procfile);
}
#elif defined (__sun__)
psinfo_t info;
int procfd;
@@ -741,13 +695,8 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
struct kinfo_proc *kproc;
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
if (kproc && cnt > 0) {
#if defined(__FreeBSD__)
*vsz = kproc->ki_size;
*rss = kproc->ki_rssize * uwsgi.page_size;
#elif defined(__DragonFly__)
*vsz = kproc->kp_vm_map_size;
*rss = kproc->kp_vm_rssize * uwsgi.page_size;
#endif
}
#elif defined(UWSGI_NEW_OPENBSD)
struct kinfo_proc *kproc;
@@ -812,7 +761,6 @@ void uwsgi_register_logger(char *name, ssize_t(*func) (struct uwsgi_logger *, ch
ul->configured = 0;
ul->fd = -1;
ul->data = NULL;
ul->buf = NULL;
#ifdef UWSGI_DEBUG
@@ -837,24 +785,6 @@ void uwsgi_append_logger(struct uwsgi_logger *ul) {
}
}
void uwsgi_append_req_logger(struct uwsgi_logger *ul) {
if (!uwsgi.choosen_req_logger) {
uwsgi.choosen_req_logger = ul;
return;
}
struct uwsgi_logger *ucl = uwsgi.choosen_req_logger;
while (ucl) {
if (!ucl->next) {
ucl->next = ul;
return;
}
ucl = ucl->next;
}
}
struct uwsgi_logger *uwsgi_get_logger(char *name) {
struct uwsgi_logger *ul = uwsgi.loggers;
@@ -925,13 +855,13 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
if (uwsgi.logvectors[wsgi_req->async_id][pos].iov_len == 0 && logchunk->type != 0) {
uwsgi.logvectors[wsgi_req->async_id][pos].iov_base = (char *) empty_var;
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 1;
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 1;
}
logchunk = logchunk->next;
}
// do not check for errors
rlen = writev(uwsgi.req_log_fd, uwsgi.logvectors[wsgi_req->async_id], uwsgi.logformat_vectors);
rlen = writev(2, uwsgi.logvectors[wsgi_req->async_id], uwsgi.logformat_vectors);
// free allocated memory
logchunk = uwsgi.logchunks;
@@ -1006,25 +936,24 @@ static ssize_t uwsgi_lf_status(struct wsgi_request *wsgi_req, char **buf) {
return strlen(*buf);
}
static ssize_t uwsgi_lf_rsize(struct wsgi_request *wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->response_size);
return strlen(*buf);
*buf = uwsgi_num2str(wsgi_req->response_size);
return strlen(*buf);
}
static ssize_t uwsgi_lf_hsize(struct wsgi_request *wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->headers_size);
return strlen(*buf);
*buf = uwsgi_num2str(wsgi_req->headers_size);
return strlen(*buf);
}
static ssize_t uwsgi_lf_size(struct wsgi_request *wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->headers_size+wsgi_req->response_size);
return strlen(*buf);
*buf = uwsgi_num2str(wsgi_req->headers_size+wsgi_req->response_size);
return strlen(*buf);
}
static ssize_t uwsgi_lf_cl(struct wsgi_request *wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->post_cl);
return strlen(*buf);
*buf = uwsgi_num2str(wsgi_req->post_cl);
return strlen(*buf);
}
@@ -1048,19 +977,19 @@ static ssize_t uwsgi_lf_time(struct wsgi_request * wsgi_req, char **buf) {
return strlen(*buf);
}
static ssize_t uwsgi_lf_ltime(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_malloc(64);
time_t now = wsgi_req->start_of_request / 1000000;
size_t ret = strftime(*buf, 64, "%d/%b/%Y:%H:%M:%S %z", localtime(&now));
if (ret == 0) {
*buf[0] = 0;
return 0;
}
return ret;
*buf = uwsgi_malloc(64);
time_t now = wsgi_req->start_of_request / 1000000;
size_t ret = strftime(*buf, 64, "%d/%b/%Y:%H:%M:%S %z", localtime(&now));
if (ret == 0) {
*buf[0] = 0;
return 0;
}
return ret;
}
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
return strlen(*buf);
@@ -1117,17 +1046,17 @@ static ssize_t uwsgi_lf_rssM(struct wsgi_request * wsgi_req, char **buf) {
}
static ssize_t uwsgi_lf_pktsize(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->uh->pktsize);
*buf = uwsgi_num2str(wsgi_req->uh.pktsize);
return strlen(*buf);
}
static ssize_t uwsgi_lf_modifier1(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->uh->modifier1);
*buf = uwsgi_num2str(wsgi_req->uh.modifier1);
return strlen(*buf);
}
static ssize_t uwsgi_lf_modifier2(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->uh->modifier2);
*buf = uwsgi_num2str(wsgi_req->uh.modifier2);
return strlen(*buf);
}
@@ -1194,38 +1123,38 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->pos_len = offsetof(struct wsgi_request, protocol_len);
}
else if (!uwsgi_strncmp(ptr, len, "uagent", 6)) {
logchunk->pos = offsetof(struct wsgi_request, user_agent);
logchunk->pos_len = offsetof(struct wsgi_request, user_agent_len);
}
else if (!uwsgi_strncmp(ptr, len, "referer", 7)) {
logchunk->pos = offsetof(struct wsgi_request, referer);
logchunk->pos_len = offsetof(struct wsgi_request, referer_len);
}
logchunk->pos = offsetof(struct wsgi_request, user_agent);
logchunk->pos_len = offsetof(struct wsgi_request, user_agent_len);
}
else if (!uwsgi_strncmp(ptr, len, "referer", 7)) {
logchunk->pos = offsetof(struct wsgi_request, referer);
logchunk->pos_len = offsetof(struct wsgi_request, referer_len);
}
else if (!uwsgi_strncmp(ptr, len, "status", 6)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_status;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "rsize", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_rsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "hsize", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_hsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "size", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_size;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "cl", 2)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_cl;
logchunk->free = 1;
}
logchunk->type = 3;
logchunk->func = uwsgi_lf_rsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "hsize", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_hsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "size", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_size;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "cl", 2)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_cl;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "micros", 6)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_micros;
@@ -1242,10 +1171,10 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ltime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ltime;
logchunk->free = 1;
}
logchunk->type = 3;
logchunk->func = uwsgi_lf_ltime;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ctime", 5)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_ctime;
@@ -1327,169 +1256,3 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
}
}
}
int uwsgi_master_log(void) {
ssize_t rlen = read(uwsgi.shared->worker_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
if (rlen > 0) {
#ifdef UWSGI_PCRE
uwsgi_alarm_log_check(uwsgi.log_master_buf, rlen);
struct uwsgi_regexp_list *url = uwsgi.log_drain_rules;
while (url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
return 0;
}
url = url->next;
}
if (uwsgi.log_filter_rules) {
int show = 0;
url = uwsgi.log_filter_rules;
while (url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
show = 1;
break;
}
url = url->next;
}
if (!show)
return 0;
}
url = uwsgi.log_route;
int finish = 0;
while (url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
if (ul_route) {
ul_route->func(ul_route, uwsgi.log_master_buf, rlen);
finish = 1;
}
}
url = url->next;
}
if (finish)
return 0;
#endif
int raw_log = 1;
struct uwsgi_logger *ul = uwsgi.choosen_logger;
while (ul) {
// check for named logger
if (ul->id) {
goto next;
}
ul->func(ul, uwsgi.log_master_buf, rlen);
raw_log = 0;
next:
ul = ul->next;
}
if (raw_log) {
rlen = write(uwsgi.original_log_fd, uwsgi.log_master_buf, rlen);
}
return 0;
}
return -1;
}
int uwsgi_master_req_log(void) {
ssize_t rlen = read(uwsgi.shared->worker_req_log_pipe[0], uwsgi.log_master_buf, uwsgi.log_master_bufsize);
if (rlen > 0) {
#ifdef UWSGI_PCRE
struct uwsgi_regexp_list *url = uwsgi.log_req_route;
int finish = 0;
while (url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, uwsgi.log_master_buf, rlen) >= 0) {
struct uwsgi_logger *ul_route = (struct uwsgi_logger *) url->custom_ptr;
if (ul_route) {
ul_route->func(ul_route, uwsgi.log_master_buf, rlen);
finish = 1;
}
}
url = url->next;
}
if (finish)
return 0;
#endif
int raw_log = 1;
struct uwsgi_logger *ul = uwsgi.choosen_req_logger;
while (ul) {
// check for named logger
if (ul->id) {
goto next;
}
ul->func(ul, uwsgi.log_master_buf, rlen);
raw_log = 0;
next:
ul = ul->next;
}
if (raw_log) {
rlen = write(uwsgi.original_log_fd, uwsgi.log_master_buf, rlen);
}
return 0;
}
return -1;
}
static void *logger_thread_loop(void *noarg) {
struct pollfd logpoll[2];
// block all signals
sigset_t smask;
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
logpoll[0].events = POLLIN;
logpoll[0].fd = uwsgi.shared->worker_log_pipe[0];
int logpolls = 1;
if (uwsgi.req_log_master) {
logpoll[1].events = POLLIN;
logpoll[1].fd = uwsgi.shared->worker_req_log_pipe[0];
}
for (;;) {
int ret = poll(logpoll, logpolls, -1);
if (ret > 0) {
if (logpoll[0].revents & POLLIN) {
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
uwsgi_master_log();
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
}
else if (logpolls > 1 && logpoll[1].revents & POLLIN) {
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
uwsgi_master_req_log();
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
}
}
}
return NULL;
}
void uwsgi_threaded_logger_spawn() {
pthread_t logger_thread;
if (pthread_create(&logger_thread, NULL, logger_thread_loop, NULL)) {
uwsgi_error("pthread_create()");
uwsgi_log("falling back to non-threaded logger...\n");
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_log_pipe[0]);
if (uwsgi.req_log_master) {
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.shared->worker_req_log_pipe[0]);
}
uwsgi.threaded_logger = 0;
}
}
+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;
}
+900 -209
View File
File diff suppressed because it is too large Load Diff
-305
View File
@@ -1,305 +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;
if (uwsgi.status.chain_reloading > uwsgi.numproc) {
uwsgi.status.chain_reloading = 0;
uwsgi_log_verbose("chain reloading complete\n");
}
int i;
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()");
}
}
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;
}
}
}
}
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;
}
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;
}
}
-174
View File
@@ -1,174 +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;
}
}
// 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 (interesting_fd == uwsgi.emperor_fd) {
uwsgi_master_manage_emperor();
return 0;
}
}
// 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;
}
+244 -475
View File
@@ -5,82 +5,15 @@ extern struct uwsgi_server uwsgi;
void worker_wakeup() {
}
uint64_t uwsgi_worker_exceptions(int wid) {
uint64_t total = 0;
int i;
for(i=0;i<uwsgi.cores;i++) {
total += uwsgi.workers[wid].cores[i].exceptions;
}
return total;
}
void uwsgi_curse(int wid, int sig) {
uwsgi.workers[wid].cursed_at = uwsgi_now();
uwsgi.workers[wid].no_mercy_at = uwsgi.workers[wid].cursed_at + uwsgi.worker_reload_mercy;
if (sig) {
(void) kill(uwsgi.workers[wid].pid, sig);
}
}
static void uwsgi_signal_spoolers(int signum) {
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
if (uspool->pid > 0) {
kill(uspool->pid, signum);
uwsgi_log("killing the spooler with pid %d\n", uspool->pid);
}
uspool = uspool->next;
}
}
void uwsgi_destroy_processes() {
int i;
int waitpid_status;
uwsgi_signal_spoolers(SIGKILL);
if (uwsgi.emperor_pid >= 0) {
kill(uwsgi.emperor_pid, SIGKILL);
waitpid(uwsgi.emperor_pid, &waitpid_status, 0);
uwsgi_log("The Emperor has been buried (pid: %d)\n", (int) uwsgi.emperor_pid);
}
uwsgi_detach_daemons();
for (i = 0; i < ushared->gateways_cnt; i++) {
if (ushared->gateways[i].pid > 0) {
kill(ushared->gateways[i].pid, SIGKILL);
waitpid(ushared->gateways[i].pid, &waitpid_status, 0);
uwsgi_log("gateway \"%s %d\" has been buried (pid: %d)\n", ushared->gateways[i].name, ushared->gateways[i].num, (int) ushared->gateways[i].pid);
}
}
// TODO mules can be programmed to be gracefully reloaded
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].pid > 0) {
kill(uwsgi.mules[i].pid, SIGKILL);
waitpid(uwsgi.mules[i].pid, &waitpid_status, 0);
uwsgi_log("mule %d has been buried (pid: %d)\n", i, (int) uwsgi.mules[i].pid);
}
}
}
void uwsgi_master_cleanup_hooks(void) {
int j;
// could be an inherited atexit hook
if (uwsgi.mypid != uwsgi.workers[0].pid)
if (uwsgi.mywid > 0)
return;
uwsgi.status.is_cleaning = 1;
uwsgi.cleaning = 1;
for (j = 0; j < uwsgi.gp_cnt; j++) {
if (uwsgi.gp[j]->master_cleanup) {
@@ -145,7 +78,8 @@ int uwsgi_calc_cheaper(void) {
#endif
uwsgi.workers[oldest_worker].cheaped = 1;
uwsgi.workers[oldest_worker].manage_next_request = 0;
uwsgi_curse(oldest_worker, SIGWINCH);
// wakeup task in case of wait
(void) kill(uwsgi.workers[oldest_worker].pid, SIGWINCH);
}
}
@@ -197,7 +131,7 @@ int uwsgi_cheaper_algo_spare(void) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
// if a non-busy worker is found, the overload_count is decremented and stop the cycle
if (uwsgi_worker_is_busy(i) == 0) {
if (uwsgi.workers[i].busy == 0) {
if (overload_count > 0)
overload_count--;
goto healthy;
@@ -240,7 +174,7 @@ healthy:
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
active_workers++;
if (uwsgi_worker_is_busy(i) == 1)
if (uwsgi.workers[i].busy == 1)
busy_workers++;
}
}
@@ -351,9 +285,6 @@ void uwsgi_reload(char **argv) {
/* check fd table (a module can obviosly open some fd on initialization...) */
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int) uwsgi.max_fd);
for (i = 3; i < (int) uwsgi.max_fd; i++) {
if (uwsgi_fd_is_safe(i)) continue;
int found = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
@@ -376,59 +307,48 @@ void uwsgi_reload(char **argv) {
uwsgi_sock = uwsgi_sock->next;
}
if (found) continue;
if (uwsgi.has_emperor) {
if (i == uwsgi.emperor_fd) {
continue;
if (!found) {
if (uwsgi.has_emperor) {
if (i == uwsgi.emperor_fd) {
found = 1;
}
}
if (i == uwsgi.emperor_fd_config) {
continue;
}
}
if (uwsgi.alarm_thread) {
if (i == uwsgi.alarm_thread->queue) continue;
if (i == uwsgi.alarm_thread->pipe[0]) continue;
if (i == uwsgi.alarm_thread->pipe[1]) continue;
}
if (uwsgi.log_master) {
if (uwsgi.original_log_fd > -1) {
if (i == uwsgi.original_log_fd) {
continue;
found = 1;
}
}
if (uwsgi.shared->worker_log_pipe[0] > -1) {
if (i == uwsgi.shared->worker_log_pipe[0]) {
continue;
found = 1;
}
}
if (uwsgi.shared->worker_log_pipe[1] > -1) {
if (i == uwsgi.shared->worker_log_pipe[1]) {
continue;
found = 1;
}
}
}
if (!found) {
#ifdef __APPLE__
fcntl(i, F_SETFD, FD_CLOEXEC);
fcntl(i, F_SETFD, FD_CLOEXEC);
#else
close(i);
close(i);
#endif
}
}
#ifndef UWSGI_IPCSEM_ATEXIT
// free ipc semaphores if in use
if (uwsgi.lock_engine && !strcmp(uwsgi.lock_engine, "ipcsem")) {
uwsgi_ipcsem_clear();
}
#endif
#ifdef UWSGI_AS_SHARED_LIBRARY
return;
#else
uwsgi_log("running %s\n", uwsgi.binary_path);
uwsgi_flush_logs();
argv[0] = uwsgi.binary_path;
@@ -449,13 +369,48 @@ void uwsgi_reload(char **argv) {
uwsgi_error("execvp()");
// never here
exit(1);
#endif
}
void master_check_cluster_nodes() {
int i;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_STATIC && ucn->status == UWSGI_NODE_FAILED) {
// should i retry ?
if (uwsgi.master_cycles % ucn->errors == 0) {
if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
ucn->status = UWSGI_NODE_OK;
uwsgi_log("re-enabled cluster node %d/%s\n", i, ucn->name);
}
else {
ucn->errors++;
}
}
}
else if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_DYNAMIC) {
// if the last_seen attr is higher than 30 secs ago, mark the node as dead
if ((uwsgi.current_time - ucn->last_seen) > 30) {
uwsgi_log_verbose("no presence announce in the last 30 seconds by node %s, i assume it is dead.\n", ucn->name);
ucn->name[0] = 0;
}
}
}
}
void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
int i;
// close the cache server
if (uwsgi.cache_server_fd != -1) {
close(uwsgi.cache_server_fd);
}
if (uwsgi.master_process) {
if (uwsgi.master_queue > -1)
close(uwsgi.master_queue);
@@ -488,13 +443,14 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
close(uwsgi.workers[i].signal_pipe[1]);
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.i_am_a_spooler && uwsgi.i_am_a_spooler->pid != getpid()) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1)
close(uwsgi.shared->spooler_signal_pipe[0]);
if (uwsgi.shared->spooler_signal_pipe[1] != -1)
close(uwsgi.shared->spooler_signal_pipe[1]);
}
#endif
if (uwsgi.shared->mule_signal_pipe[0] != -1)
close(uwsgi.shared->mule_signal_pipe[0]);
@@ -547,13 +503,11 @@ int uwsgi_respawn_worker(int wid) {
uwsgi.workers[wid].pending_harakiri = 0;
uwsgi.workers[wid].rss_size = 0;
uwsgi.workers[wid].vsz_size = 0;
// ... reset stopped_at
uwsgi.workers[wid].cursed_at = 0;
uwsgi.workers[wid].no_mercy_at = 0;
// internal statuses should be reset too
uwsgi.workers[wid].cheaped = 0;
uwsgi.workers[wid].busy = 0;
// SUSPENSION is managed by the user, not the master...
//uwsgi.workers[wid].suspended = 0;
uwsgi.workers[wid].sig = 0;
@@ -594,6 +548,7 @@ int uwsgi_respawn_worker(int wid) {
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
/*
uwsgi.workers[uwsgi.mywid].cheaped = 0;
uwsgi.workers[uwsgi.mywid].busy = 0;
uwsgi.workers[uwsgi.mywid].suspended = 0;
uwsgi.workers[uwsgi.mywid].sig = 0;
*/
@@ -602,17 +557,16 @@ int uwsgi_respawn_worker(int wid) {
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
// reset wsgi_request structures
for(i=0;i<uwsgi.cores;i++) {
uwsgi.workers[uwsgi.mywid].cores[i].in_request = 0;
memset(&uwsgi.workers[uwsgi.mywid].cores[i].req, 0, sizeof(struct wsgi_request));
}
for(i=0;i<uwsgi.cores;i++) {
memset(&uwsgi.workers[uwsgi.mywid].cores[i].req, 0, sizeof(struct wsgi_request));
}
uwsgi_fixup_fds(wid, 0, NULL);
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
if (uwsgi.master_process) {
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.status.is_cheap)) {
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
@@ -646,6 +600,178 @@ int uwsgi_respawn_worker(int wid) {
return 0;
}
void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
// fix month
uwsgi_cron_delta->tm_mon++;
uwsgi_lock(uwsgi.cron_table_lock);
for (i = 0; i < ushared->cron_cnt; i++) {
struct uwsgi_cron *ucron = &ushared->cron[i];
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = ucron->minute;
uc_hour = ucron->hour;
uc_day = ucron->day;
uc_month = ucron->month;
uc_week = ucron->week;
// negative values as interval -1 = * , -5 = */5
if (ucron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(ucron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (ucron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(ucron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (ucron->month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(ucron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (ucron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(ucron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (ucron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(ucron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (ucron->day >= 0 && ucron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, signal it ?
if (now - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = now;
}
}
}
uwsgi_unlock(uwsgi.cron_table_lock);
}
else {
uwsgi_error("localtime()");
}
}
void uwsgi_manage_command_cron(time_t now) {
struct tm *uwsgi_cron_delta;
struct uwsgi_cron *current_cron = uwsgi.crons;
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
uwsgi_error("localtime()");
return;
}
// fix month
uwsgi_cron_delta->tm_mon++;
while (current_cron) {
uc_minute = current_cron->minute;
uc_hour = current_cron->hour;
uc_day = current_cron->day;
uc_month = current_cron->month;
uc_week = current_cron->week;
// negative values as interval -1 = * , -5 = */5
if (current_cron->minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(current_cron->minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (current_cron->hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (current_cron->month < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(current_cron->month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (current_cron->day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(current_cron->day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (current_cron->week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(current_cron->week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (current_cron->day >= 0 && current_cron->week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (run_task == 1) {
// date match, run command ?
if (now - current_cron->last_job > 60) {
//call command
if (current_cron->command) {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
}
}
current_cron->last_job = now;
}
}
current_cron = current_cron->next;
}
}
struct uwsgi_stats *uwsgi_master_generate_stats() {
int i;
@@ -696,20 +822,11 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
while (ud) {
if (uwsgi_stats_object_open(us))
goto end;
// allocate 2x the size of original command
// in case we need to escape all chars
char *cmd = uwsgi_malloc(strlen(ud->command)*2);
escape_json(ud->command, strlen(ud->command), cmd);
if (uwsgi_stats_keyval_comma(us, "cmd", cmd)) {
free(cmd);
if (uwsgi_stats_keyval_comma(us, "cmd", ud->command))
goto end;
}
free(cmd);
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) (ud->pid < 0) ? 0 : ud->pid))
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) ud->pid))
goto end;
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) ud->respawns ? 0 : ud->respawns))
if (uwsgi_stats_keylong(us, "respawns", (unsigned long long) (ud->respawns - 1)))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
@@ -750,72 +867,6 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_comma(us))
goto end;
if (uwsgi.caches) {
if (uwsgi_stats_key(us, "caches"))
goto end;
if (uwsgi_stats_list_open(us)) goto end;
struct uwsgi_cache *uc = uwsgi.caches;
while(uc) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyval_comma(us, "name", uc->name ? uc->name : "default"))
goto end;
if (uwsgi_stats_keyval_comma(us, "hash", uc->hash->name))
goto end;
if (uwsgi_stats_keylong_comma(us, "hashsize", (unsigned long long) uc->hashsize))
goto end;
if (uwsgi_stats_keylong_comma(us, "keysize", (unsigned long long) uc->keysize))
goto end;
if (uwsgi_stats_keylong_comma(us, "max_items", (unsigned long long) uc->max_items))
goto end;
if (uwsgi_stats_keylong_comma(us, "blocks", (unsigned long long) uc->blocks))
goto end;
if (uwsgi_stats_keylong_comma(us, "blocksize", (unsigned long long) uc->blocksize))
goto end;
if (uwsgi_stats_keylong_comma(us, "items", (unsigned long long) uc->n_items))
goto end;
if (uwsgi_stats_keylong_comma(us, "hits", (unsigned long long) uc->hits))
goto end;
if (uwsgi_stats_keylong_comma(us, "miss", (unsigned long long) uc->miss))
goto end;
if (uwsgi_stats_keylong_comma(us, "full", (unsigned long long) uc->full))
goto end;
if (uwsgi_stats_keylong(us, "last_modified_at", (unsigned long long) uc->last_modified_at))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
if (uc->next) {
if (uwsgi_stats_comma(us))
goto end;
}
uc = uc->next;
}
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
}
if (uwsgi_stats_key(us, "sockets"))
goto end;
@@ -875,7 +926,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
goto end;
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi_worker_exceptions(i + 1)))
if (uwsgi_stats_keylong_comma(us, "exceptions", (unsigned long long) uwsgi.workers[i + 1].exceptions))
goto end;
if (uwsgi_stats_keylong_comma(us, "harakiri_count", (unsigned long long) uwsgi.workers[i + 1].harakiri_count))
goto end;
@@ -893,7 +944,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keyval_comma(us, "status", "cheap"))
goto end;
}
else if (uwsgi.workers[i + 1].suspended && !uwsgi_worker_is_busy(i+1)) {
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
if (uwsgi_stats_keyval_comma(us, "status", "pause"))
goto end;
}
@@ -902,7 +953,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keyvalnum_comma(us, "status", "sig", (unsigned long long) uwsgi.workers[i + 1].signum))
goto end;
}
else if (uwsgi_worker_is_busy(i+1)) {
else if (uwsgi.workers[i + 1].busy) {
if (uwsgi_stats_keyval_comma(us, "status", "busy"))
goto end;
}
@@ -1007,21 +1058,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_keylong_comma(us, "offloaded_requests", (unsigned long long) uc->offloaded_requests))
goto end;
if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors))
goto end;
if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request))
goto end;
if (uwsgi_stats_key(us, "vars"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
if (uwsgi_stats_dump_vars(us, uc)) goto end;
if (uwsgi_stats_list_close(us))
if (uwsgi_stats_keylong(us, "in_request", (unsigned long long) uc->in_request))
goto end;
@@ -1049,6 +1086,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_list_close(us))
goto end;
#ifdef UWSGI_SPOOLER
struct uwsgi_spooler *uspool = uwsgi.spoolers;
if (uspool) {
if (uwsgi_stats_comma(us))
@@ -1087,209 +1125,12 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
if (uwsgi_stats_list_close(us))
goto end;
}
struct uwsgi_cron *ucron = uwsgi.crons;
if (ucron) {
if (uwsgi_stats_comma(us))
goto end;
if (uwsgi_stats_key(us, "crons"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
while (ucron) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyslong_comma(us, "minute", (long long) ucron->minute))
goto end;
if (uwsgi_stats_keyslong_comma(us, "hour", (long long) ucron->hour))
goto end;
if (uwsgi_stats_keyslong_comma(us, "day", (long long) ucron->day))
goto end;
if (uwsgi_stats_keyslong_comma(us, "month", (long long) ucron->month))
goto end;
if (uwsgi_stats_keyslong_comma(us, "week", (long long) ucron->week))
goto end;
char *cmd = uwsgi_malloc(strlen(ucron->command)*2);
escape_json(ucron->command, strlen(ucron->command), cmd);
if (uwsgi_stats_keyval_comma(us, "command", cmd)) {
free(cmd);
goto end;
}
free(cmd);
if (uwsgi_stats_keylong_comma(us, "unique", (unsigned long long) ucron->unique))
goto end;
#ifdef UWSGI_SSL
if (uwsgi_stats_keyval_comma(us, "legion", ucron->legion ? ucron->legion : ""))
goto end;
#endif
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) ucron->pid))
goto end;
if (uwsgi_stats_keylong(us, "started_at", (unsigned long long) ucron->started_at))
goto end;
if (uwsgi_stats_object_close(us))
goto end;
ucron = ucron->next;
if (ucron) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
}
#ifdef UWSGI_SSL
struct uwsgi_legion *legion = NULL;
if (uwsgi.legions) {
if (uwsgi_stats_comma(us))
goto end;
if (uwsgi_stats_key(us, "legions"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
legion = uwsgi.legions;
while (legion) {
if (uwsgi_stats_object_open(us))
goto end;
if (uwsgi_stats_keyval_comma(us, "legion", legion->legion))
goto end;
if (uwsgi_stats_keyval_comma(us, "addr", legion->addr))
goto end;
if (uwsgi_stats_keyval_comma(us, "uuid", legion->uuid))
goto end;
if (uwsgi_stats_keylong_comma(us, "valor", (unsigned long long) legion->valor))
goto end;
if (uwsgi_stats_keylong_comma(us, "checksum", (unsigned long long) legion->checksum))
goto end;
if (uwsgi_stats_keylong_comma(us, "quorum", (unsigned long long) legion->quorum))
goto end;
if (uwsgi_stats_keylong_comma(us, "i_am_the_lord", (unsigned long long) legion->i_am_the_lord))
goto end;
if (uwsgi_stats_keylong_comma(us, "lord_valor", (unsigned long long) legion->lord_valor))
goto end;
if (uwsgi_stats_keyvaln_comma(us, "lord_uuid", legion->lord_uuid, 36))
goto end;
// legion nodes start
if (uwsgi_stats_key(us, "nodes"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
struct uwsgi_string_list *nodes = legion->nodes;
while (nodes) {
if (uwsgi_stats_str(us, nodes->value))
goto end;
nodes = nodes->next;
if (nodes) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
// legion members start
if (uwsgi_stats_key(us, "members"))
goto end;
if (uwsgi_stats_list_open(us))
goto end;
uwsgi_rlock(legion->lock);
struct uwsgi_legion_node *node = legion->nodes_head;
while (node) {
if (uwsgi_stats_object_open(us))
goto unlock_legion_mutex;
if (uwsgi_stats_keyvaln_comma(us, "name", node->name, node->name_len))
goto unlock_legion_mutex;
if (uwsgi_stats_keyval_comma(us, "uuid", node->uuid))
goto unlock_legion_mutex;
if (uwsgi_stats_keylong_comma(us, "valor", (unsigned long long) node->valor))
goto unlock_legion_mutex;
if (uwsgi_stats_keylong_comma(us, "checksum", (unsigned long long) node->checksum))
goto unlock_legion_mutex;
if (uwsgi_stats_keylong(us, "last_seen", (unsigned long long) node->last_seen))
goto unlock_legion_mutex;
if (uwsgi_stats_object_close(us))
goto unlock_legion_mutex;
node = node->next;
if (node) {
if (uwsgi_stats_comma(us))
goto unlock_legion_mutex;
}
}
uwsgi_rwunlock(legion->lock);
if (uwsgi_stats_list_close(us))
goto end;
// legion nodes end
if (uwsgi_stats_object_close(us))
goto end;
legion = legion->next;
if (legion) {
if (uwsgi_stats_comma(us))
goto end;
}
}
if (uwsgi_stats_list_close(us))
goto end;
}
#endif
if (uwsgi_stats_object_close(us))
goto end;
return us;
#ifdef UWSGI_SSL
unlock_legion_mutex:
if (legion)
uwsgi_rwunlock(legion->lock);
#endif
end:
free(us->base);
free(us);
@@ -1386,75 +1227,3 @@ void trigger_harakiri(int i) {
// to avoid races
}
void uwsgi_master_fix_request_counters() {
int i;
uint64_t total_counter = 0;
for (i = 1; i <= uwsgi.numproc;i++) {
uint64_t tmp_counter = 0;
int j;
for(j=0;j<uwsgi.cores;j++) {
tmp_counter += uwsgi.workers[i].cores[j].requests;
}
uwsgi.workers[i].requests = tmp_counter;
total_counter += tmp_counter;
}
uwsgi.workers[0].requests = total_counter;
}
int uwsgi_cron_task_needs_execution(struct tm *uwsgi_cron_delta, int minute, int hour, int day, int month, int week) {
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uc_minute = minute;
uc_hour = hour;
uc_day = day;
uc_month = month;
uc_week = week;
// negative values as interval -1 = * , -5 = */5
if (minute < 0) {
if ((uwsgi_cron_delta->tm_min % abs(minute)) == 0) {
uc_minute = uwsgi_cron_delta->tm_min;
}
}
if (hour < 0) {
if ((uwsgi_cron_delta->tm_hour % abs(hour)) == 0) {
uc_hour = uwsgi_cron_delta->tm_hour;
}
}
if (month < 0) {
if ((uwsgi_cron_delta->tm_mon % abs(month)) == 0) {
uc_month = uwsgi_cron_delta->tm_mon;
}
}
if (day < 0) {
if ((uwsgi_cron_delta->tm_mday % abs(day)) == 0) {
uc_day = uwsgi_cron_delta->tm_mday;
}
}
if (week < 0) {
if ((uwsgi_cron_delta->tm_wday % abs(week)) == 0) {
uc_week = uwsgi_cron_delta->tm_wday;
}
}
int run_task = 0;
// mday and wday are ORed
if (day >= 0 && week >= 0) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
return run_task;
}
-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:
}
}
+19 -31
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;
@@ -416,12 +405,12 @@ void uwsgi_setup_mules_and_farms() {
uwsgi.mules = (struct uwsgi_mule *) uwsgi_calloc_shared(sizeof(struct uwsgi_mule) * uwsgi.mules_cnt);
create_signal_pipe(uwsgi.shared->mule_signal_pipe);
create_msg_pipe(uwsgi.shared->mule_queue_pipe, uwsgi.mule_msg_size);
create_signal_pipe(uwsgi.shared->mule_queue_pipe);
for (i = 0; i < uwsgi.mules_cnt; i++) {
// create the socket pipe
create_signal_pipe(uwsgi.mules[i].signal_pipe);
create_msg_pipe(uwsgi.mules[i].queue_pipe, uwsgi.mule_msg_size);
create_signal_pipe(uwsgi.mules[i].queue_pipe);
uwsgi.mules[i].id = i + 1;
@@ -447,11 +436,10 @@ 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);
create_signal_pipe(uwsgi.farms[i].queue_pipe);
char *p = strtok(mules_list, ",");
while (p != NULL) {
@@ -468,7 +456,7 @@ void uwsgi_setup_mules_and_farms() {
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);
}
+73 -342
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__)
ssize_t len = sendfile(uor->fd2, uor->fd, &uor->pos, 128 * 1024);
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__)
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);
}
+4 -3
View File
@@ -24,7 +24,7 @@ static void uwsgi_plugin_parse_section(char *filename) {
}
#endif
int plugin_already_loaded(const char *plugin) {
static int plugin_already_loaded(const char *plugin) {
int i;
for (i = 0; i < 256; i++) {
@@ -76,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];
@@ -165,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;
}
+1 -2
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);
@@ -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) {
-572
View File
@@ -1,572 +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;
}
*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 -1576
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));
}
+163 -64
View File
@@ -2,74 +2,173 @@
extern struct uwsgi_server uwsgi;
// sendfile() abstraction
ssize_t uwsgi_sendfile_do(int sockfd, int filefd, size_t pos, size_t len) {
ssize_t uwsgi_sendfile(struct wsgi_request * wsgi_req) {
#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__)
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__)
off_t off = pos;
return sendfile(sockfd, filefd, &off, len);
#else
// 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];
if (pos > 0) {
if (lseek(filefd, pos, SEEK_SET)) {
uwsgi_error("uwsgi_sendfile_do()/seek()");
return -1;
int fd = wsgi_req->sendfile_fd;
int sockfd = wsgi_req->poll.fd;
struct stat stat_buf;
ssize_t sst = 0;
if (!wsgi_req->sendfile_fd_size) {
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) {
#if defined(__FreeBSD__) || defined(__DragonFly__)
int sf_ret;
off_t sf_len = filesize;
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
}
/*
simple non blocking sendfile implementation
(generally used as fallback)
*/
int uwsgi_simple_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
wsgi_req->write_pos = 0;
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;
}
}
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) {
+151 -33
View File
@@ -6,9 +6,7 @@ int uwsgi_signal_handler(uint8_t sig) {
struct uwsgi_signal_entry *use = NULL;
int pos = (uwsgi.mywid * 256) + sig;
use = &uwsgi.shared->signal_table[pos];
use = &uwsgi.shared->signal_table[sig];
if (!use->handler)
return -1;
@@ -57,11 +55,13 @@ int uwsgi_signal_handler(uint8_t sig) {
set_mule_harakiri(uwsgi.shared->options[UWSGI_OPTION_MULE_HARAKIRI]);
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
}
}
#endif
int ret = uwsgi.p[use->modifier1]->signal_handler(sig, use->handler);
@@ -77,19 +77,20 @@ int uwsgi_signal_handler(uint8_t sig) {
set_mule_harakiri(0);
}
}
#ifdef UWSGI_SPOOLER
else if (uwsgi.i_am_a_spooler && (getpid() == uwsgi.i_am_a_spooler->pid)) {
if (uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
set_spooler_harakiri(0);
}
}
#endif
return ret;
}
int uwsgi_signal_registered(uint8_t sig) {
int pos = (uwsgi.mywid * 256) + sig;
if (uwsgi.shared->signal_table[pos].handler != NULL)
if (uwsgi.shared->signal_table[sig].handler != NULL)
return 1;
return 0;
@@ -99,26 +100,15 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
struct uwsgi_signal_entry *use = NULL;
if (!uwsgi.master_process) {
uwsgi_log("you cannot register signals without a master\n");
return -1;
}
if (uwsgi.mywid == 0 && uwsgi.workers[0].pid != uwsgi.mypid) {
uwsgi_log("only the master and the workers can register signal handlers\n");
return -1;
}
if (strlen(receiver) > 63)
return -1;
uwsgi_lock(uwsgi.signal_table_lock);
int pos = (uwsgi.mywid * 256) + sig;
use = &uwsgi.shared->signal_table[pos];
use = &uwsgi.shared->signal_table[sig];
if (use->handler && uwsgi.mywid == 0) {
uwsgi_log("[uwsgi-signal] you cannot re-register a signal as the master !!!\n");
if (use->handler) {
uwsgi_log("[uwsgi-signal] you cannot re-register a signal !!!\n");
uwsgi_unlock(uwsgi.signal_table_lock);
return -1;
}
@@ -135,15 +125,6 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: %s)\n", sig, uwsgi.mywid, modifier1, receiver);
}
// check for cow
if (uwsgi.mywid == 0) {
int i;
for(i=1;i<=uwsgi.numproc;i++) {
int pos = (i * 256);
memcpy(&uwsgi.shared->signal_table[pos], &uwsgi.shared->signal_table[0], sizeof(struct uwsgi_signal_entry) * 256);
}
}
uwsgi_unlock(uwsgi.signal_table_lock);
return 0;
@@ -180,9 +161,88 @@ int uwsgi_add_file_monitor(uint8_t sig, char *filename) {
}
int uwsgi_add_timer(uint8_t sig, int secs) {
struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **up, char *name, int (*func) (int, struct uwsgi_signal_probe *)) {
if (!uwsgi.master_process) return -1;
struct uwsgi_probe *uwsgi_up = *up, *old_up;
if (!uwsgi_up) {
*up = uwsgi_malloc(sizeof(struct uwsgi_probe));
uwsgi_up = *up;
}
else {
while (uwsgi_up) {
old_up = uwsgi_up;
uwsgi_up = uwsgi_up->next;
}
uwsgi_up = uwsgi_malloc(sizeof(struct uwsgi_probe));
old_up->next = uwsgi_up;
}
uwsgi_up->name = name;
uwsgi_up->func = func;
uwsgi_up->next = NULL;
uwsgi_log("registered new probe \"%s\" at %p\n", name, uwsgi_up);
return uwsgi_up;
}
int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq) {
uwsgi_lock(uwsgi.probe_table_lock);
if (ushared->probes_cnt < MAX_PROBES) {
struct uwsgi_probe *up = uwsgi.probes;
while (up) {
if (!strcmp(up->name, kind)) {
break;
}
up = up->next;
}
if (!up) {
uwsgi_log("unable to find probe \"%s\" !!!\n", kind);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
// fill the probe table
ushared->probes[ushared->probes_cnt].func = up->func;
strncpy(ushared->probes[ushared->probes_cnt].args, args, 1024 - 1);
ushared->probes[ushared->probes_cnt].registered = 0;
ushared->probes[ushared->probes_cnt].sig = sig;
ushared->probes[ushared->probes_cnt].fd = -1;
ushared->probes[ushared->probes_cnt].state = 0;
ushared->probes[ushared->probes_cnt].last_event = 0;
ushared->probes[ushared->probes_cnt].data = NULL;
ushared->probes[ushared->probes_cnt].cycles = 0;
ushared->probes[ushared->probes_cnt].bad = 0;
if (!timeout) {
timeout = uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT];
}
ushared->probes[ushared->probes_cnt].timeout = timeout;
if (!freq) {
freq = 1;
}
ushared->probes[ushared->probes_cnt].freq = freq;
ushared->probes_cnt++;
}
else {
uwsgi_log("you can register max %d probes !!!\n", MAX_PROBES);
uwsgi_unlock(uwsgi.probe_table_lock);
return -1;
}
uwsgi_unlock(uwsgi.probe_table_lock);
return 0;
}
int uwsgi_add_timer(uint8_t sig, int secs) {
uwsgi_lock(uwsgi.timer_table_lock);
@@ -206,6 +266,63 @@ int uwsgi_add_timer(uint8_t sig, int secs) {
}
void uwsgi_opt_add_cron(char *opt, char *value, void *foobar) {
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(value, "%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 = value + i;
}
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;
}
int uwsgi_signal_add_rb_timer(uint8_t sig, int secs, int iterations) {
if (!uwsgi.master_process)
@@ -309,8 +426,7 @@ int uwsgi_signal_send(int fd, uint8_t sig) {
void uwsgi_route_signal(uint8_t sig) {
int pos = (uwsgi.mywid * 256) + sig;
struct uwsgi_signal_entry *use = &ushared->signal_table[pos];
struct uwsgi_signal_entry *use = &ushared->signal_table[sig];
int i;
// send to first available worker
@@ -341,6 +457,7 @@ void uwsgi_route_signal(uint8_t sig) {
else if (!strcmp(use->receiver, "subscribed")) {
}
// route to spooler
#ifdef UWSGI_SPOOLER
else if (!strcmp(use->receiver, "spooler")) {
if (ushared->worker_signal_pipe[0] != -1) {
if (uwsgi_signal_send(ushared->spooler_signal_pipe[0], sig)) {
@@ -348,6 +465,7 @@ void uwsgi_route_signal(uint8_t sig) {
}
}
}
#endif
else if (!strcmp(use->receiver, "mules")) {
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi_signal_send(uwsgi.mules[i].signal_pipe[0], sig)) {
@@ -462,7 +580,7 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
if (ret == 0) {
goto destroy;
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
uwsgi_error("[uwsgi-signal] read()");
goto destroy;
}
+6 -15
View File
@@ -1,4 +1,6 @@
#include <uwsgi.h>
#ifdef UWSGI_SNMP
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
@@ -406,17 +408,6 @@ int uwsgi_setup_snmp(void) {
return snmp_fd;
}
void uwsgi_master_manage_snmp(int snmp_fd) {
struct sockaddr_in udp_client;
socklen_t udp_len = sizeof(udp_client);
ssize_t rlen = recvfrom(snmp_fd, uwsgi.wsgi_req->buffer, uwsgi.buffer_size, 0, (struct sockaddr *) &udp_client, &udp_len);
if (rlen < 0) {
uwsgi_error("recvfrom()");
}
else if (rlen > 0) {
manage_snmp(snmp_fd, (uint8_t *) uwsgi.wsgi_req->buffer, rlen, &udp_client);
}
}
#else
#warning "*** SNMP support is disabled ***"
#endif
+158 -275
View File
@@ -2,27 +2,6 @@
extern struct uwsgi_server uwsgi;
static int connect_to_unix(char *, int, int);
static int connect_to_tcp(char *, int, int, int);
static int connect_to_udp(char *, int);
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
size_t sock1_len = strlen(sock1);
size_t sock2_len = strlen(sock2);
if (!uwsgi_starts_with(sock1, sock1_len, "0.0.0.0:", 8)) {
sock1 += 7;
sock1_len = strlen(sock1);
}
if (!uwsgi_starts_with(sock2, sock2_len, "0.0.0.0:", 8)) {
sock2 += 7;
sock2_len = strlen(sock2);
}
return uwsgi_strncmp(sock1, sock1_len, sock2, sock2_len);
}
char *uwsgi_getsockname(int fd) {
socklen_t socket_type_len = sizeof(struct sockaddr_un);
@@ -70,7 +49,6 @@ int bind_to_unix_dgram(char *socket_name) {
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (unlink(socket_name) != 0 && errno != ENOENT) {
@@ -90,7 +68,6 @@ int bind_to_unix_dgram(char *socket_name) {
#endif
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
return serverfd;
@@ -106,7 +83,6 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (strlen(socket_name) > 102) {
uwsgi_log("invalid socket name\n");
uwsgi_nuclear_blast();
return -1;
}
if (socket_name[0] == '@') {
@@ -120,7 +96,6 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (uws_addr == NULL) {
uwsgi_error("malloc()");
uwsgi_nuclear_blast();
return -1;
}
memset(uws_addr, 0, sizeof(struct sockaddr_un));
@@ -128,7 +103,6 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (abstract_socket == 0) {
if (unlink(socket_name) != 0 && errno != ENOENT) {
@@ -140,24 +114,6 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
uwsgi_log("setting abstract socket mode (warning: only Linux supports this)\n");
}
if (uwsgi.so_sndbuf) {
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_SNDBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (uwsgi.so_rcvbuf) {
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_RCVBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
uws_addr->sun_family = AF_UNIX;
if (socket_name[0] == '@') {
memcpy(uws_addr->sun_path + abstract_socket, socket_name + 1, UMIN(strlen(socket_name + 1), 101));
@@ -184,14 +140,12 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
#endif
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
return -1;
}
// chmod unix socket for lazy users
@@ -214,6 +168,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
return serverfd;
}
#ifdef UWSGI_UDP
int bind_to_udp(char *socket_name, int multicast, int broadcast) {
int serverfd;
struct sockaddr_in uws_addr;
@@ -221,7 +176,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
int bcast = 1;
int reuse = 1;
#ifdef UWSGI_MULTICAST
struct ip_mreq mc;
uint8_t loop = 1;
#endif
udp_port = strchr(socket_name, ':');
if (udp_port == NULL) {
@@ -238,6 +196,7 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(atoi(udp_port + 1));
#ifdef UWSGI_MULTICAST
if (!broadcast && !multicast) {
char quad[4];
char *first_part = strchr(socket_name, '.');
@@ -248,6 +207,9 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
multicast = 1;
}
}
#else
if (!broadcast) {
#endif
if (!strcmp(socket_name, "255.255.255.255")) {
broadcast = 1;
}
@@ -274,12 +236,14 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
uwsgi_error("setsockopt()");
}
#ifdef UWSGI_MULTICAST
if (multicast) {
// if multicast is enabled remember to bind to INADDR_ANY
uws_addr.sin_addr.s_addr = INADDR_ANY;
mc.imr_multiaddr.s_addr = inet_addr(socket_name);
mc.imr_interface.s_addr = INADDR_ANY;
}
#endif
if (broadcast) {
if (setsockopt(serverfd, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast))) {
@@ -295,9 +259,10 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
return -1;
}
#ifdef UWSGI_MULTICAST
if (multicast) {
uwsgi_log("[uwsgi-mcast] joining multicast group: %s:%d\n", socket_name, ntohs(uws_addr.sin_port));
if (setsockopt(serverfd, IPPROTO_IP, IP_MULTICAST_LOOP, &uwsgi.multicast_loop, sizeof(uwsgi.multicast_loop))) {
uwsgi_log("[uWSGI] joining multicast group: %s:%d\n", socket_name, ntohs(uws_addr.sin_port));
if (setsockopt(serverfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop))) {
uwsgi_error("setsockopt()");
}
@@ -310,52 +275,44 @@ int bind_to_udp(char *socket_name, int multicast, int broadcast) {
}
}
#endif
udp_port[0] = ':';
return serverfd;
}
static int uwsgi_connect_do(char *socket_name, int timeout, int async) {
char *tcp_port = strchr(socket_name, ':');
if (tcp_port) {
tcp_port[0] = 0;
tcp_port++;
return connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
}
return connect_to_unix(socket_name, timeout, async);
}
#endif
int uwsgi_connectn(char *socket_name, uint16_t len, int timeout, int async) {
int fd;
char *zeroed_socket_name = uwsgi_concat2n(socket_name, len, "", 0);
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
fd = uwsgi_connect(zeroed_socket_name, timeout, async);
free(zeroed_socket_name);
return fd;
}
int uwsgi_connect(char *socket_name, int timeout, int async) {
char *zeroed_socket_name = uwsgi_str(socket_name);
int fd = uwsgi_connect_do(zeroed_socket_name, timeout, async);
free(zeroed_socket_name);
return fd;
int ret;
char *tcp_port = strchr(socket_name, ':');
if (tcp_port) {
tcp_port[0] = 0;
tcp_port++;
ret = connect_to_tcp(socket_name, atoi(tcp_port), timeout, async);
// reset the socket name
tcp_port--;
tcp_port[0] = ':';
return ret;
}
return connect_to_unix(socket_name, timeout, async);
}
int uwsgi_connect_udp(char *socket_name) {
int fd = -1;
char *zeroed_socket_name = uwsgi_str(socket_name);
char *udp_port = strchr(zeroed_socket_name, ':');
if (!udp_port) goto end;
*udp_port = 0;
udp_port++;
fd = connect_to_udp(zeroed_socket_name, atoi(udp_port));
end:
free(zeroed_socket_name);
return fd;
}
static int connect_to_unix(char *socket_name, int timeout, int async) {
int connect_to_unix(char *socket_name, int timeout, int async) {
struct pollfd uwsgi_poll;
struct sockaddr_un uws_addr;
@@ -400,7 +357,7 @@ static int connect_to_unix(char *socket_name, int timeout, int async) {
}
static int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
struct pollfd uwsgi_poll;
struct sockaddr_in uws_addr;
@@ -417,13 +374,15 @@ static int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
socket_name[strlen(socket_name)] = ':';
#if defined(__linux__) && defined(SOCK_NONBLOCK) && !defined(OBSOLETE_LINUX_KERNEL)
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
#else
uwsgi_poll.fd = socket(AF_INET, SOCK_STREAM, 0);
#endif
if (uwsgi_poll.fd < 0) {
uwsgi_error("connect_to_tcp()/socket()");
uwsgi_error("socket()");
return -1;
}
@@ -439,38 +398,6 @@ static int connect_to_tcp(char *socket_name, int port, int timeout, int async) {
}
static int connect_to_udp(char *socket_name, int port) {
struct sockaddr_in uws_addr;
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
uws_addr.sin_port = htons(port);
if (socket_name[0] == 0) {
uws_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) {
uwsgi_error("connect_to_udp()/socket()");
return -1;
}
if (connect(fd, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_in))) {
close(fd);
return -1;
}
return fd;
}
char *generate_socket_name(char *socket_name) {
char *asterisk = strchr(socket_name, '*');
@@ -547,7 +474,7 @@ char *generate_socket_name(char *socket_name) {
}
uwsgi_log("unable to find a valid socket address\n");
uwsgi_log("unable to find avalid socket address\n");
#endif
uwsgi_nuclear_blast();
}
@@ -620,58 +547,20 @@ socklen_t socket_to_in_addr(char *socket_name, char *port, int portn, struct soc
int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
int serverfd;
#ifdef AF_INET6
struct sockaddr_in6 uws_addr;
#else
struct sockaddr_in uws_addr;
#endif
int reuse = 1;
int family = AF_INET;
socklen_t addr_len = sizeof(struct sockaddr_in);
#ifdef AF_INET6
if (socket_name[0] == '[' && tcp_port[-1] == ']') {
family = AF_INET6;
socket_to_in_addr6(socket_name, tcp_port, 0, &uws_addr);
addr_len = sizeof(struct sockaddr_in6);
}
else {
#endif
socket_to_in_addr(socket_name, tcp_port, 0, (struct sockaddr_in *) &uws_addr);
#ifdef AF_INET6
}
#endif
socket_to_in_addr(socket_name, tcp_port, 0, &uws_addr);
serverfd = socket(family, SOCK_STREAM, 0);
serverfd = socket(AF_INET, SOCK_STREAM, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
return -1;
}
if (uwsgi.so_sndbuf) {
socklen_t sndbuf = (socklen_t) uwsgi.so_sndbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDBUF, &sndbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_SNDBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (uwsgi.so_rcvbuf) {
socklen_t rcvbuf = (socklen_t) uwsgi.so_rcvbuf;
if (setsockopt(serverfd, SOL_SOCKET, SO_RCVBUF, &rcvbuf, sizeof(socklen_t)) < 0) {
uwsgi_error("SO_RCVBUF setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEADDR setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
#ifdef __linux__
@@ -682,7 +571,6 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
uwsgi_error("IP_FREEBIND setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
#endif
@@ -692,26 +580,12 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
uwsgi_error("SO_REUSEPORT setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
#else
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
#endif
}
if (uwsgi.tcp_fast_open) {
#ifdef TCP_FASTOPEN
if (setsockopt(serverfd, SOL_TCP, TCP_FASTOPEN, (const void *) &uwsgi.tcp_fast_open, sizeof(int)) < 0) {
uwsgi_error("TCP_FASTOPEN setsockopt()");
}
else {
uwsgi_log("TCP_FASTOPEN enabled on %s\n", socket_name);
}
#else
uwsgi_log("!!! your system does not support TCP_FASTOPEN !!!\n");
#endif
}
if (uwsgi.so_send_timeout) {
struct timeval tv;
tv.tv_sec = uwsgi.so_send_timeout;
@@ -719,7 +593,6 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
uwsgi_error("SO_SNDTIMEO setsockopt()");
uwsgi_nuclear_blast();
return -1;
}
}
@@ -748,28 +621,25 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
}
if (bind(serverfd, (struct sockaddr *) &uws_addr, addr_len) != 0) {
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
if (errno == EADDRINUSE) {
uwsgi_log("probably another instance of uWSGI is running on the same address (%s).\n", socket_name);
}
uwsgi_error("bind()");
uwsgi_nuclear_blast();
return -1;
}
#ifdef __linux__
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn", 1);
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%i).\n", somaxconn);
uwsgi_nuclear_blast();
return -1;
}
#endif
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
return -1;
}
@@ -837,16 +707,7 @@ int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_s
}
#endif
#ifdef MSG_FASTOPEN
if (addr->sa_family == AF_INET && uwsgi.tcp_fast_open_client) {
ret = sendto(fdpoll->fd, "", 0, MSG_FASTOPEN, addr, addr_size);
}
else {
#endif
ret = connect(fdpoll->fd, addr, addr_size);
#ifdef MSG_FASTOPEN
}
#endif
ret = connect(fdpoll->fd, addr, addr_size);
if (async) {
if (ret < 0 && errno != EINPROGRESS) {
@@ -1062,7 +923,6 @@ struct uwsgi_socket *uwsgi_new_socket(char *name) {
char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
char *auto_ip = inet_ntoa(sin.sin_addr);
uwsgi_sock->name = uwsgi_concat3n(auto_ip, strlen(auto_ip), ":", 1, auto_port, strlen(auto_port));
free(auto_port);
}
}
@@ -1182,7 +1042,7 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
}
}
}
#ifdef AF_INET6
#ifdef UWSGI_IPV6
else if (gsa.sa->sa_family == AF_INET6) {
char *computed_addr;
char computed_port[6];
@@ -1498,7 +1358,87 @@ nextsock:
}
#ifdef AF_INET6
#ifdef UWSGI_IPV6
int bind_to_tcp6(char *socket_name, int listen_queue, char *tcp_port) {
int serverfd;
struct sockaddr_in6 uws_addr;
int reuse = 1;
socket_to_in_addr6(socket_name, tcp_port, 0, &uws_addr);
serverfd = socket(AF_INET6, SOCK_STREAM, 0);
if (serverfd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
uwsgi_nuclear_blast();
}
#ifdef __linux__
#ifdef IP_FREEBIND
if (uwsgi.freebind) {
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
uwsgi_nuclear_blast();
}
}
#endif
#endif
if (uwsgi.reuse_port) {
#ifdef SO_REUSEPORT
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
uwsgi_nuclear_blast();
}
#else
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
#endif
}
if (!uwsgi.no_defer_accept) {
#ifdef __linux__
if (setsockopt(serverfd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], sizeof(int))) {
uwsgi_error("setsockopt()");
}
// OSX has no SO_ACCEPTFILTER !!!
#elif defined(__freebsd__)
struct accept_filter_arg afa;
strcpy(afa.af_name, "dataready");
afa.af_arg[0] = 0;
if (setsockopt(serverfd, SOL_SOCKET, SO_ACCEPTFILTER, &afa, sizeof(struct accept_filter_arg))) {
uwsgi_error("setsockopt()");
}
#endif
}
if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
if (errno == EADDRINUSE) {
uwsgi_log("probably another instance of uWSGI is running on the same address.\n");
}
uwsgi_error("bind()");
uwsgi_nuclear_blast();
}
if (listen(serverfd, listen_queue) != 0) {
uwsgi_error("listen()");
uwsgi_nuclear_blast();
}
if (tcp_port)
tcp_port[0] = ':';
return serverfd;
}
socklen_t socket_to_in_addr6(char *socket_name, char *port, int portn, struct sockaddr_in6 * sin_addr) {
memset(sin_addr, 0, sizeof(struct sockaddr_in6));
@@ -1552,14 +1492,11 @@ void uwsgi_setup_shared_sockets() {
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
shared_sock->family = AF_UNIX;
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
if (uwsgi.chown_socket) {
uwsgi_chown(shared_sock->name, uwsgi.chown_socket);
}
}
else {
#ifdef AF_INET6
#ifdef UWSGI_IPV6
if (shared_sock->name[0] == '[' && tcp_port[-1] == ']') {
shared_sock->fd = bind_to_tcp(shared_sock->name, uwsgi.listen_queue, tcp_port);
shared_sock->fd = bind_to_tcp6(shared_sock->name, uwsgi.listen_queue, tcp_port);
shared_sock->family = AF_INET6;
// fix socket name
shared_sock->name = uwsgi_getsockname(shared_sock->fd);
@@ -1572,7 +1509,7 @@ void uwsgi_setup_shared_sockets() {
// fix socket name
shared_sock->name = uwsgi_getsockname(shared_sock->fd);
uwsgi_log("uwsgi shared socket %d bound to TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
#ifdef AF_INET6
#ifdef UWSGI_IPV6
}
#endif
}
@@ -1591,7 +1528,7 @@ void uwsgi_setup_shared_sockets() {
for (i = 3; i < (int) uwsgi.max_fd; i++) {
char *sock = uwsgi_getsockname(i);
if (sock) {
if (!uwsgi_socket_strcmp(sock, shared_sock->name)) {
if (!strcmp(sock, shared_sock->name)) {
if (strchr(sock, ':')) {
uwsgi_log("uwsgi shared socket %d inherited TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
shared_sock->family = AF_INET;
@@ -1602,7 +1539,9 @@ void uwsgi_setup_shared_sockets() {
}
shared_sock->fd = i;
}
free(sock);
else {
free(sock);
}
}
}
}
@@ -1716,9 +1655,9 @@ void uwsgi_bind_sockets() {
uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
}
else {
#ifdef AF_INET6
#ifdef UWSGI_IPV6
if (uwsgi_sock->name[0] == '[' && tcp_port[-1] == ']') {
uwsgi_sock->fd = bind_to_tcp(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
uwsgi_sock->fd = bind_to_tcp6(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
uwsgi_log("uwsgi socket %d bound to TCP6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
uwsgi_sock->family = AF_INET6;
}
@@ -1727,7 +1666,7 @@ void uwsgi_bind_sockets() {
uwsgi_sock->fd = bind_to_tcp(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
uwsgi_log("uwsgi socket %d bound to TCP address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
uwsgi_sock->family = AF_INET;
#ifdef AF_INET6
#ifdef UWSGI_IPV6
}
#endif
}
@@ -1803,14 +1742,14 @@ void uwsgi_bind_sockets() {
uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (uwsgi_sock->auto_port) {
#ifdef AF_INET6
#ifdef UWSGI_IPV6
if (uwsgi_sock->family == AF_INET6) {
uwsgi_log("uwsgi socket %d bound to TCP6 address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
}
else {
#endif
uwsgi_log("uwsgi socket %d bound to TCP address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
#ifdef AF_INET6
#ifdef UWSGI_IPV6
}
#endif
}
@@ -1821,7 +1760,6 @@ void uwsgi_bind_sockets() {
}
void uwsgi_set_sockets_protocols() {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
char *requested_protocol = uwsgi_sock->proto_name;
@@ -1843,7 +1781,6 @@ void uwsgi_set_sockets_protocols() {
}
}
setup_proto:
if (!requested_protocol) {
requested_protocol = uwsgi.protocol;
@@ -1852,70 +1789,28 @@ setup_proto:
if (requested_protocol && !strcmp("http", requested_protocol)) {
uwsgi_sock->proto = uwsgi_proto_http_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
uwsgi_sock->proto_sendfile = NULL;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
}
else if (requested_protocol && (!strcmp("fastcgi", requested_protocol) || !strcmp("fcgi", requested_protocol))) {
if (uwsgi.protocol && (!strcmp(uwsgi.protocol, "fastcgi") || !strcmp(uwsgi.protocol, "fcgi"))) {
uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
}
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_fastcgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_fastcgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_fastcgi_writev_header;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("fastcgi-nph", requested_protocol) || !strcmp("fcgi-nph", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_fastcgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_fastcgi_read_body;
uwsgi_sock->proto_write = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_fastcgi_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_fastcgi_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_fastcgi_close;
}
else if (requested_protocol && (!strcmp("scgi", requested_protocol) || !strcmp("scgi", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_cgi_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
else if (requested_protocol && (!strcmp("scgi-nph", requested_protocol) || !strcmp("scgi-nph", requested_protocol))) {
uwsgi_sock->proto = uwsgi_proto_scgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
}
#ifdef UWSGI_ZEROMQ
else if (requested_protocol && !strcmp("zmq", requested_protocol)) {
uwsgi.zeromq = 1;
@@ -1924,13 +1819,11 @@ setup_proto:
else {
uwsgi_sock->proto = uwsgi_proto_uwsgi_parser;
uwsgi_sock->proto_accept = uwsgi_proto_base_accept;
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
uwsgi_sock->proto_write = uwsgi_proto_base_write;
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
uwsgi_sock->proto_write = uwsgi_proto_uwsgi_write;
uwsgi_sock->proto_writev = uwsgi_proto_uwsgi_writev;
uwsgi_sock->proto_write_header = uwsgi_proto_uwsgi_write_header;
uwsgi_sock->proto_writev_header = uwsgi_proto_uwsgi_writev_header;
uwsgi_sock->proto_sendfile = NULL;
uwsgi_sock->proto_close = uwsgi_proto_base_close;
if (uwsgi.offload_threads > 0)
uwsgi_sock->can_offload = 1;
@@ -1941,13 +1834,3 @@ nextsock:
}
void uwsgi_tcp_nodelay(int fd) {
#ifdef TCP_NODELAY
int flag = 1;
if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int))) {
uwsgi_error("uwsgi_tcp_nodelay()/setsockopt()");
}
#endif
}
+23 -23
View File
@@ -1,3 +1,4 @@
#ifdef UWSGI_SPOOLER
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
@@ -108,6 +109,7 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.mywid = -1;
uwsgi.mypid = getpid();
uspool->pid = uwsgi.mypid;
// avoid race conditions !!!
@@ -122,7 +124,21 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
}
}
uwsgi_spooler_run();
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
spooler(uspool);
}
else if (pid > 0) {
uwsgi_log("spawned the uWSGI spooler on dir %s with pid %d\n", uspool->dir, pid);
@@ -131,26 +147,6 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
return pid;
}
void uwsgi_spooler_run() {
int i;
struct uwsgi_spooler *uspool = uwsgi.i_am_a_spooler;
uwsgi.signal_socket = uwsgi.shared->spooler_signal_pipe[1];
for (i = 0; i < 256; i++) {
if (uwsgi.p[i]->spooler_init) {
uwsgi.p[i]->spooler_init();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->spooler_init) {
uwsgi.gp[i]->spooler_init();
}
}
spooler(uspool);
}
void destroy_spool(char *dir, char *file) {
if (chdir(dir)) {
@@ -259,7 +255,7 @@ int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core
close(fd);
if (!uwsgi.spooler_quiet)
uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) size + body_len + 4, filename);
uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);
// and here waiting threads can continue
uwsgi_unlock(uspool->lock);
@@ -552,7 +548,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
uspool->tasks++;
if (ret == -2) {
if (!uwsgi.spooler_quiet)
uwsgi_log("[spooler %s pid: %d] done with task %s after %lld seconds\n", uspool->dir, (int) uwsgi.mypid, task, (long long) uwsgi_now() - now);
uwsgi_log("[spooler %s pid: %d] done with task %s after %d seconds\n", uspool->dir, (int) uwsgi.mypid, task, uwsgi_now() - now);
destroy_spool(dir, task);
}
// re-spool it
@@ -588,3 +584,7 @@ void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {
}
}
}
#else
#warning "*** Spooler support is disabled ***"
#endif
+57
View File
@@ -0,0 +1,57 @@
#ifdef UWSGI_SQLITE3
#include "uwsgi.h"
#include <sqlite3.h>
extern struct uwsgi_server uwsgi;
static int uwsgi_sqlite3_config_callback(void *magic_table, int field_count, char **fields, char **col) {
// make a copy of the string
if (field_count >= 2) {
int value_len = strlen(fields[1]) + 1;
char *value = magic_sub(fields[1], value_len, &value_len, (char **) magic_table);
add_exported_option(uwsgi_strncopy(fields[0], strlen(fields[0])), value, 0);
}
return 0;
}
void uwsgi_sqlite3_config(char *file, char *magic_table[]) {
sqlite3 *db;
char *err = NULL;
char *query = "SELECT * FROM uwsgi";
char *colon = uwsgi_get_last_char(file, ':');
if (colon) {
colon[0] = 0;
if (colon[1] != 0) {
query = colon + 1;
}
}
uwsgi_log("[uWSGI] getting sqlite3 configuration from %s\n", file);
#ifdef sqlite3_open_v2
if (sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL)) {
#else
if (sqlite3_open(file, &db)) {
#endif
uwsgi_log("unable to open sqlite3 db: %s\n", sqlite3_errmsg(db));
sqlite3_close(db);
exit(1);
}
if (sqlite3_exec(db, query, uwsgi_sqlite3_config_callback, (void *) magic_table, &err)) {
uwsgi_log("sqlite3 error: %s\n", err);
sqlite3_close(db);
exit(1);
}
sqlite3_close(db);
}
#endif
-516
View File
@@ -1,516 +0,0 @@
#include <uwsgi.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
extern struct uwsgi_server uwsgi;
/*
ssl additional datas are retrieved via indexes.
You can create an index with SSL_CTX_get_ex_new_index and
set data in it with SSL_CTX_set_ex_data
*/
void uwsgi_ssl_init(void) {
OPENSSL_config(NULL);
SSL_library_init();
SSL_load_error_strings();
OpenSSL_add_all_algorithms();
uwsgi.ssl_initialized = 1;
}
void uwsgi_ssl_info_cb(SSL const *ssl, int where, int ret) {
if (where & SSL_CB_HANDSHAKE_DONE) {
if (ssl->s3) {
ssl->s3->flags |= SSL3_FLAGS_NO_RENEGOTIATE_CIPHERS;
}
}
}
int uwsgi_ssl_verify_callback(int ok, X509_STORE_CTX * x509_store) {
return 1;
}
int uwsgi_ssl_session_new_cb(SSL *ssl, SSL_SESSION *sess) {
char session_blob[4096];
int len = i2d_SSL_SESSION(sess, NULL);
if (len > 4096) {
if (uwsgi.ssl_verbose) {
uwsgi_log("[uwsgi-ssl] unable to store session of size %d\n", len);
}
return 0;
}
unsigned char *p = (unsigned char *) session_blob;
i2d_SSL_SESSION(sess, &p);
// ok let's write the value to the cache
uwsgi_wlock(uwsgi.ssl_sessions_cache->lock);
if (uwsgi_cache_set2(uwsgi.ssl_sessions_cache, (char *) sess->session_id, sess->session_id_length, session_blob, len, uwsgi.ssl_sessions_timeout, 0)) {
if (uwsgi.ssl_verbose) {
uwsgi_log("[uwsgi-ssl] unable to store session of size %d in the cache\n", len);
}
}
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
return 0;
}
SSL_SESSION *uwsgi_ssl_session_get_cb(SSL *ssl, unsigned char *key, int keylen, int *copy) {
uint64_t valsize = 0;
*copy = 0;
uwsgi_rlock(uwsgi.ssl_sessions_cache->lock);
char *value = uwsgi_cache_get2(uwsgi.ssl_sessions_cache, (char *)key, keylen, &valsize);
if (!value) {
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
if (uwsgi.ssl_verbose) {
uwsgi_log("[uwsgi-ssl] cache miss\n");
}
return NULL;
}
SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&value, valsize);
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
return sess;
}
void uwsgi_ssl_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *sess) {
uwsgi_wlock(uwsgi.ssl_sessions_cache->lock);
if (uwsgi_cache_del2(uwsgi.ssl_sessions_cache, (char *) sess->session_id, sess->session_id_length, 0, 0)) {
if (uwsgi.ssl_verbose) {
uwsgi_log("[uwsgi-ssl] error removing cache item\n");
}
}
uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
}
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
static int uwsgi_sni_cb(SSL *ssl, int *ad, void *arg) {
const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
if (!servername) return SSL_TLSEXT_ERR_NOACK;
size_t servername_len = strlen(servername);
struct uwsgi_string_list *usl = uwsgi.sni;
while(usl) {
if (!uwsgi_strncmp(usl->value, usl->len, (char *)servername, servername_len)) {
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
return SSL_TLSEXT_ERR_OK;
}
usl = usl->next;
}
#ifdef UWSGI_PCRE
struct uwsgi_regexp_list *url = uwsgi.sni_regexp;
while(url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, (char *)servername, servername_len) >= 0) {
SSL_set_SSL_CTX(ssl, url->custom_ptr);
return SSL_TLSEXT_ERR_OK;
}
url = url->next;
}
#endif
if (uwsgi.sni_dir) {
size_t sni_dir_len = strlen(uwsgi.sni_dir);
char *sni_dir_cert = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".crt", 4);
char *sni_dir_key = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".key", 4);
char *sni_dir_client_ca = uwsgi_concat4n(uwsgi.sni_dir, sni_dir_len, "/", 1, (char *) servername, servername_len, ".ca", 3);
if (uwsgi_file_exists(sni_dir_cert) && uwsgi_file_exists(sni_dir_key)) {
char *client_ca = NULL;
if (uwsgi_file_exists(sni_dir_client_ca)) {
client_ca = sni_dir_client_ca;
}
usl = uwsgi_ssl_add_sni_item(uwsgi_str((char *)servername), sni_dir_cert, sni_dir_key, uwsgi.sni_dir_ciphers, client_ca);
if (!usl) goto done;
free(sni_dir_cert);
free(sni_dir_key);
free(sni_dir_client_ca);
SSL_set_SSL_CTX(ssl, usl->custom_ptr);
uwsgi_log("[uwsgi-sni for pid %d] added context for %s\n", (int) getpid(), servername);
return SSL_TLSEXT_ERR_OK;
}
done:
free(sni_dir_cert);
free(sni_dir_key);
free(sni_dir_client_ca);
}
return SSL_TLSEXT_ERR_NOACK;
}
#endif
SSL_CTX *uwsgi_ssl_new_server_context(char *name, char *crt, char *key, char *ciphers, char *client_ca) {
SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
if (!ctx) {
uwsgi_log("[uwsgi-ssl] unable to initialize context \"%s\"\n", name);
return NULL;
}
// this part is taken from nginx and stud, removing unneeded functionality
// stud (for me) has made the best choice on choosing DH approach
long ssloptions = SSL_OP_NO_SSLv2 | SSL_OP_ALL | SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION;
// disable compression (if possibile)
#ifdef SSL_OP_NO_COMPRESSION
ssloptions |= SSL_OP_NO_COMPRESSION;
#endif
// release/reuse buffers as soon as possibile
#ifdef SSL_MODE_RELEASE_BUFFERS
SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
#endif
if (SSL_CTX_use_certificate_chain_file(ctx, crt) <= 0) {
uwsgi_log("[uwsgi-ssl] unable to assign certificate %s for context \"%s\"\n", crt, name);
SSL_CTX_free(ctx);
return NULL;
}
// this part is based from stud
BIO *bio = BIO_new_file(crt, "r");
if (bio) {
DH *dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL);
BIO_free(bio);
if (dh) {
SSL_CTX_set_tmp_dh(ctx, dh);
DH_free(dh);
#if OPENSSL_VERSION_NUMBER >= 0x0090800fL
#ifndef OPENSSL_NO_ECDH
#ifdef NID_X9_62_prime256v1
EC_KEY *ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
SSL_CTX_set_tmp_ecdh(ctx, ecdh);
EC_KEY_free(ecdh);
#endif
#endif
#endif
}
}
if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM) <= 0) {
uwsgi_log("[uwsgi-ssl] unable to assign key %s for context \"%s\"\n", key, name);
SSL_CTX_free(ctx);
return NULL;
}
// if ciphers are specified, prefer server ciphers
if (ciphers && strlen(ciphers) > 0) {
if (SSL_CTX_set_cipher_list(ctx, ciphers) == 0) {
uwsgi_log("[uwsgi-ssl] unable to set requested ciphers (%s) for context \"%s\"\n", ciphers, name);
SSL_CTX_free(ctx);
return NULL;
}
ssloptions |= SSL_OP_CIPHER_SERVER_PREFERENCE;
}
// set session context (if possibile), this is required for client certificate authentication
if (name) {
SSL_CTX_set_session_id_context(ctx, (unsigned char *) name, strlen(name));
}
if (client_ca) {
if (client_ca[0] == '!') {
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, uwsgi_ssl_verify_callback);
client_ca++;
}
else {
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, uwsgi_ssl_verify_callback);
}
// in the future we should allow to set the verify depth
SSL_CTX_set_verify_depth(ctx, 1);
if (SSL_CTX_load_verify_locations(ctx, client_ca, NULL) == 0) {
uwsgi_log("[uwsgi-ssl] unable to set ssl verify locations (%s) for context \"%s\"\n", client_ca, name);
SSL_CTX_free(ctx);
return NULL;
}
STACK_OF(X509_NAME) * list = SSL_load_client_CA_file(client_ca);
if (!list) {
uwsgi_log("unable to load client CA certificate (%s) for context \"%s\"\n", client_ca, name);
SSL_CTX_free(ctx);
return NULL;
}
SSL_CTX_set_client_CA_list(ctx, list);
}
SSL_CTX_set_info_callback(ctx, uwsgi_ssl_info_cb);
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
SSL_CTX_set_tlsext_servername_callback(ctx, uwsgi_sni_cb);
#endif
// disable session caching by default
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
if (uwsgi.ssl_sessions_use_cache) {
// we need to early initialize locking and caching
uwsgi_setup_locking();
uwsgi_cache_create_all();
uwsgi.ssl_sessions_cache = uwsgi_cache_by_name(uwsgi.ssl_sessions_use_cache);
if (!uwsgi.ssl_sessions_cache) {
// check for default cache
if (!strcmp(uwsgi.ssl_sessions_use_cache, "true") && uwsgi.caches) {
uwsgi.ssl_sessions_cache = uwsgi.caches;
}
else {
uwsgi_log("unable to find cache \"%s\"\n", uwsgi.ssl_sessions_use_cache ? uwsgi.ssl_sessions_use_cache : "default");
exit(1);
}
}
if (!uwsgi.ssl_sessions_cache->max_items) {
uwsgi_log("you have to enable uWSGI cache to use it as SSL session store !!!\n");
exit(1);
}
if (uwsgi.ssl_sessions_cache->blocksize < 4096) {
uwsgi_log("cache blocksize for SSL session store must be at least 4096 bytes\n");
exit(1);
}
SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_SERVER|
SSL_SESS_CACHE_NO_INTERNAL|
SSL_SESS_CACHE_NO_AUTO_CLEAR);
#ifdef SSL_OP_NO_TICKET
ssloptions |= SSL_OP_NO_TICKET;
#endif
// just for fun
SSL_CTX_sess_set_cache_size(ctx, 0);
// set the callback for ssl sessions
SSL_CTX_sess_set_new_cb(ctx, uwsgi_ssl_session_new_cb);
SSL_CTX_sess_set_get_cb(ctx, uwsgi_ssl_session_get_cb);
SSL_CTX_sess_set_remove_cb(ctx, uwsgi_ssl_session_remove_cb);
}
SSL_CTX_set_timeout(ctx, uwsgi.ssl_sessions_timeout);
SSL_CTX_set_options(ctx, ssloptions);
return ctx;
}
char *uwsgi_rsa_sign(char *algo_key, char *message, size_t message_len, unsigned int *s_len) {
// openssl could not be initialized
if (!uwsgi.ssl_initialized) {
uwsgi_ssl_init();
}
*s_len = 0;
EVP_PKEY *pk = NULL;
char *algo = uwsgi_str(algo_key);
char *colon = strchr(algo, ':');
if (!colon) {
uwsgi_log("invalid RSA signature syntax, must be: <digest>:<pemfile>\n");
free(algo);
return NULL;
}
*colon = 0;
char *keyfile = colon + 1;
char *signature = NULL;
FILE *kf = fopen(keyfile, "r");
if (!kf) {
uwsgi_error_open(keyfile);
free(algo);
return NULL;
}
if (PEM_read_PrivateKey(kf, &pk, NULL, NULL) == 0) {
uwsgi_log("unable to load private key: %s\n", keyfile);
free(algo);
fclose(kf);
return NULL;
}
fclose(kf);
EVP_MD_CTX *ctx = EVP_MD_CTX_create();
if (!ctx) {
free(algo);
EVP_PKEY_free(pk);
return NULL;
}
const EVP_MD *md = EVP_get_digestbyname(algo);
if (!md) {
uwsgi_log("unknown digest algo: %s\n", algo);
free(algo);
EVP_PKEY_free(pk);
EVP_MD_CTX_destroy(ctx);
return NULL;
}
*s_len = EVP_PKEY_size(pk);
signature = uwsgi_malloc(*s_len);
if (EVP_SignInit_ex(ctx, md, NULL) == 0) {
ERR_print_errors_fp(stderr);
free(signature);
signature = NULL;
*s_len = 0;
goto clear;
}
if (EVP_SignUpdate(ctx, message, message_len) == 0) {
ERR_print_errors_fp(stderr);
free(signature);
signature = NULL;
*s_len = 0;
goto clear;
}
if (EVP_SignFinal(ctx, (unsigned char *) signature, s_len, pk) == 0) {
ERR_print_errors_fp(stderr);
free(signature);
signature = NULL;
*s_len = 0;
goto clear;
}
clear:
free(algo);
EVP_PKEY_free(pk);
EVP_MD_CTX_destroy(ctx);
return signature;
}
char *uwsgi_sanitize_cert_filename(char *base, char *key, uint16_t keylen) {
uint16_t i;
char *filename = uwsgi_concat4n(base, strlen(base), "/", 1, key, keylen, ".pem\0", 5);
for (i = strlen(base) + 1; i < (strlen(base) + 1) + keylen; i++) {
if (filename[i] >= '0' && filename[i] <= '9')
continue;
if (filename[i] >= 'A' && filename[i] <= 'Z')
continue;
if (filename[i] >= 'a' && filename[i] <= 'z')
continue;
if (filename[i] == '.')
continue;
if (filename[i] == '-')
continue;
if (filename[i] == '_')
continue;
filename[i] = '_';
}
return filename;
}
char *uwsgi_ssl_rand(size_t len) {
unsigned char *buf = uwsgi_calloc(len);
if (RAND_bytes(buf, len) <= 0) {
free(buf);
return NULL;
}
return (char *) buf;
}
char *uwsgi_sha1(char *src, size_t len, char *dst) {
SHA_CTX sha;
SHA1_Init(&sha);
SHA1_Update(&sha, src, len);
SHA1_Final((unsigned char *)dst, &sha);
return dst;
}
char *uwsgi_md5(char *src, size_t len, char *dst) {
MD5_CTX md5;
MD5_Init(&md5);
MD5_Update(&md5, src, len);
MD5_Final((unsigned char *)dst, &md5);
return dst;
}
char *uwsgi_sha1_2n(char *s1, size_t len1, char *s2, size_t len2, char *dst) {
SHA_CTX sha;
SHA1_Init(&sha);
SHA1_Update(&sha, s1, len1);
SHA1_Update(&sha, s2, len2);
SHA1_Final((unsigned char *)dst, &sha);
return dst;
}
void uwsgi_opt_sni(char *opt, char *value, void *foobar) {
char *client_ca = NULL;
char *v = uwsgi_str(value);
char *space = strchr(v, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be sni_key<space>crt,key[,ciphers,client_ca]\n", opt);
exit(1);
}
*space = 0;
char *crt = space+1;
char *key = strchr(crt, ',');
if (!key) {
uwsgi_log("invalid %s syntax, must be sni_key<space>crt,key[,ciphers,client_ca]\n", opt);
exit(1);
}
*key = '\0'; key++;
char *ciphers = strchr(key, ',');
if (ciphers) {
*ciphers = '\0'; ciphers++;
client_ca = strchr(ciphers, ',');
if (client_ca) {
*client_ca = '\0'; client_ca++;
}
}
if (!uwsgi.ssl_initialized) {
uwsgi_ssl_init();
}
SSL_CTX *ctx = uwsgi_ssl_new_server_context(v, crt, key, ciphers, client_ca);
if (!ctx) {
uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", v);
free(v);
return;
}
#ifdef UWSGI_PCRE
if (!strcmp(opt, "sni-regexp")) {
struct uwsgi_regexp_list *url = uwsgi_regexp_new_list(&uwsgi.sni_regexp, v);
url->custom_ptr = ctx;
}
else {
#endif
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, v);
usl->custom_ptr = ctx;
#ifdef UWSGI_PCRE
}
#endif
}
struct uwsgi_string_list *uwsgi_ssl_add_sni_item(char *name, char *crt, char *key, char *ciphers, char *client_ca) {
if (!uwsgi.ssl_initialized) {
uwsgi_ssl_init();
}
SSL_CTX *ctx = uwsgi_ssl_new_server_context(name, crt, key, ciphers, client_ca);
if (!ctx) {
uwsgi_log("[uwsgi-ssl] DANGER unable to initialize context for \"%s\"\n", name);
return NULL;
}
struct uwsgi_string_list *usl = uwsgi_string_new_list(&uwsgi.sni, name);
usl->custom_ptr = ctx;
return usl;
}
-659
View File
@@ -1,659 +0,0 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
int uwsgi_static_want_gzip(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st) {
// check for filename size
if (*filename_len + 4 > PATH_MAX) return 0;
// check for supported encodings
if (!uwsgi_contains_n(wsgi_req->encoding, wsgi_req->encoding_len, "gzip", 4) ) return 0;
// check for 'all'
if (uwsgi.static_gzip_all) goto gzip;
// check for dirs/prefix
struct uwsgi_string_list *usl = uwsgi.static_gzip_dir;
while(usl) {
if (!uwsgi_starts_with(filename, *filename_len, usl->value, usl->len)) {
goto gzip;
}
usl = usl->next;
}
// check for ext/suffix
usl = uwsgi.static_gzip_ext;
while(usl) {
if (!uwsgi_strncmp(filename + (*filename_len - usl->len), usl->len, usl->value, usl->len)) {
goto gzip;
}
usl = usl->next;
}
#ifdef UWSGI_PCRE
// check for regexp
struct uwsgi_regexp_list *url = uwsgi.static_gzip;
while(url) {
if (uwsgi_regexp_match(url->pattern, url->pattern_extra, filename, *filename_len) >= 0) {
goto gzip;
}
url = url->next;
}
#endif
return 0;
gzip:
memcpy(filename + *filename_len, ".gz\0", 4);
*filename_len += 3;
if (stat(filename, st)) {
*filename_len -= 3;
filename[*filename_len] = 0;
return 0;
}
return 1;
}
int uwsgi_http_date(time_t t, char *dst) {
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *months[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
struct tm *hdtm = gmtime(&t);
int ret = snprintf(dst, 31, "%s, %02d %s %4d %02d:%02d:%02d GMT",
week[hdtm->tm_wday], hdtm->tm_mday, months[hdtm->tm_mon], hdtm->tm_year + 1900, hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
if (ret <= 0 || ret > 31) {
return 0;
}
return ret;
}
// only RFC 1123 is supported
static time_t parse_http_date(char *date, uint16_t len) {
struct tm hdtm;
if (len != 29 && date[3] != ',')
return 0;
hdtm.tm_mday = uwsgi_str2_num(date + 5);
switch (date[8]) {
case 'J':
if (date[9] == 'a') {
hdtm.tm_mon = 0;
break;
}
if (date[9] == 'u') {
if (date[10] == 'n') {
hdtm.tm_mon = 5;
break;
}
if (date[10] == 'l') {
hdtm.tm_mon = 6;
break;
}
return 0;
}
return 0;
case 'F':
hdtm.tm_mon = 1;
break;
case 'M':
if (date[9] != 'a')
return 0;
if (date[10] == 'r') {
hdtm.tm_mon = 2;
break;
}
if (date[10] == 'y') {
hdtm.tm_mon = 4;
break;
}
return 0;
case 'A':
if (date[10] == 'r') {
hdtm.tm_mon = 3;
break;
}
if (date[10] == 'g') {
hdtm.tm_mon = 7;
break;
}
return 0;
case 'S':
hdtm.tm_mon = 8;
break;
case 'O':
hdtm.tm_mon = 9;
break;
case 'N':
hdtm.tm_mon = 10;
break;
case 'D':
hdtm.tm_mon = 11;
break;
default:
return 0;
}
hdtm.tm_year = uwsgi_str4_num(date + 12) - 1900;
hdtm.tm_hour = uwsgi_str2_num(date + 17);
hdtm.tm_min = uwsgi_str2_num(date + 20);
hdtm.tm_sec = uwsgi_str2_num(date + 23);
return timegm(&hdtm);
}
int uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int mime_type_len, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_type;
time_t now = wsgi_req->start_of_request / 1000000;
// 30+1
char expires[31];
while (udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
udd = uwsgi.static_expires_type_mtime;
while (udd) {
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
return 0;
}
#ifdef UWSGI_PCRE
int uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filename_len, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires;
time_t now = wsgi_req->start_of_request / 1000000;
// 30+1
char expires[31];
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
udd = uwsgi.static_expires_mtime;
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
return 0;
}
int uwsgi_add_expires_path_info(struct wsgi_request *wsgi_req, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_path_info;
time_t now = wsgi_req->start_of_request / 1000000;
// 30+1
char expires[31];
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
udd = uwsgi.static_expires_path_info_mtime;
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->path_info, wsgi_req->path_info_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
return 0;
}
int uwsgi_add_expires_uri(struct wsgi_request *wsgi_req, struct stat *st) {
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_uri;
time_t now = wsgi_req->start_of_request / 1000000;
// 30+1
char expires[31];
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = uwsgi_http_date(now + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
udd = uwsgi.static_expires_uri_mtime;
while (udd) {
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, wsgi_req->uri, wsgi_req->uri_len) >= 0) {
int delta = uwsgi_str_num(udd->value, udd->vallen);
int size = uwsgi_http_date(st->st_mtime + delta, expires);
if (size > 0) {
if (uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, size)) return -1;
}
return 0;
}
udd = udd->next;
}
return 0;
}
#endif
char *uwsgi_get_mime_type(char *name, int namelen, size_t *size) {
int i;
int count = 0;
char *ext = NULL;
for (i = namelen - 1; i >= 0; i--) {
if (!isalnum((int) name[i])) {
if (name[i] == '.') {
ext = name + (namelen - count);
break;
}
}
count++;
}
if (!ext)
return NULL;
if (uwsgi.threads > 1)
pthread_mutex_lock(&uwsgi.lock_static);
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
while (udd) {
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
udd->hits++;
// auto optimization
if (udd->prev) {
if (udd->hits > udd->prev->hits) {
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
if (udd_parent) {
udd_parent->next = udd;
}
if (udd->next) {
udd->next->prev = udd_prev;
}
udd_prev->prev = udd;
udd_prev->next = udd->next;
udd->prev = udd_parent;
udd->next = udd_prev;
if (udd->prev == NULL) {
uwsgi.mimetypes = udd;
}
}
}
*size = udd->vallen;
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
return udd->value;
}
udd = udd->next;
}
if (uwsgi.threads > 1)
pthread_mutex_unlock(&uwsgi.lock_static);
return NULL;
}
ssize_t uwsgi_append_static_path(char *dir, size_t dir_len, char *file, size_t file_len) {
size_t len = dir_len;
if (len + 1 + file_len > PATH_MAX) {
return -1;
}
if (dir[len - 1] == '/') {
memcpy(dir + len, file, file_len);
dir[len + file_len] = 0;
len += file_len;
}
else {
dir[len] = '/';
memcpy(dir + len + 1, file, file_len);
dir[len + 1 + file_len] = 0;
len += 1 + file_len;
}
return len;
}
static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st, struct uwsgi_string_list **index) {
int ret = stat(filename, st);
// if non-existant return -1
if (ret < 0)
return -1;
if (S_ISREG(st->st_mode))
return 0;
// check for index
if (S_ISDIR(st->st_mode)) {
struct uwsgi_string_list *usl = uwsgi.static_index;
while (usl) {
ssize_t new_len = uwsgi_append_static_path(filename, *filename_len, usl->value, usl->len);
if (new_len >= 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %s\n", filename);
#endif
if (uwsgi_is_file2(filename, st)) {
*index = usl;
*filename_len = new_len;
return 0;
}
// reset to original name
filename[*filename_len] = 0;
}
usl = usl->next;
}
}
return -1;
}
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
size_t mime_type_size = 0;
char http_last_modified[49];
int use_gzip = 0;
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
// here we need to choose if we want the gzip variant;
if (uwsgi_static_want_gzip(wsgi_req, real_filename, &real_filename_len, st)) use_gzip = 1;
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
if (st->st_mtime <= ims) {
uwsgi_response_prepare_headers(wsgi_req, "304 Not Modified", 16);
return uwsgi_response_write_headers_do(wsgi_req);
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
#endif
size_t fsize = st->st_size;
if (wsgi_req->range_to) {
fsize = wsgi_req->range_to - wsgi_req->range_from;
if (fsize > (size_t)st->st_size) {
fsize = st->st_size;
}
}
else {
// reset in case of inconsistent size
if (wsgi_req->range_from > fsize) {
wsgi_req->range_from = 0;
fsize = 0;
}
else {
fsize -= wsgi_req->range_from;
}
}
// HTTP status
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
if (uwsgi_response_prepare_headers(wsgi_req, "206 Partial Content", 19)) return -1;
}
else {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) return -1;
}
#ifdef UWSGI_PCRE
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
uwsgi_add_expires_path_info(wsgi_req, st);
uwsgi_add_expires_uri(wsgi_req, st);
#endif
if (use_gzip) {
if (uwsgi_response_add_header(wsgi_req, "Content-Encoding", 16, "gzip", 4)) return -1;
}
// Content-Type (if available)
if (mime_type_size > 0 && mime_type) {
if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_size)) return -1;
// check for content-type related headers
uwsgi_add_expires_type(wsgi_req, mime_type, mime_type_size, st);
}
// increase static requests counter
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].static_requests++;
// nginx
if (uwsgi.file_serve_mode == 1) {
if (uwsgi_response_add_header(wsgi_req, "X-Accel-Redirect", 16, real_filename, real_filename_len)) return -1;
// this is the final header (\r\n added)
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
}
// apache
else if (uwsgi.file_serve_mode == 2) {
if (uwsgi_response_add_header(wsgi_req, "X-Sendfile", 10, real_filename, real_filename_len)) return -1;
// this is the final header (\r\n added)
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
}
// raw
else {
// set Content-Length (to fsize NOT st->st_size)
if (uwsgi_response_add_content_length(wsgi_req, fsize)) return -1;
if (fsize > 0 && (wsgi_req->range_from || wsgi_req->range_to)) {
// here use the original size !!!
if (uwsgi_response_add_content_range(wsgi_req, wsgi_req->range_from, wsgi_req->range_to, st->st_size)) return -1;
}
int size = uwsgi_http_date(st->st_mtime, http_last_modified);
if (uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, http_last_modified, size)) return -1;
// if it is a HEAD request just skip transfer
if (!uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
wsgi_req->status = 200;
return 0;
}
// Ok, the file must be transferred from uWSGI
// offloading will be automatically managed
int fd = open(real_filename, O_RDONLY);
if (fd < 0) return -1;
// fd will be closed in the following function
uwsgi_response_sendfile_do(wsgi_req, fd, wsgi_req->range_from, fsize);
}
wsgi_req->status = 200;
return 0;
}
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len, int is_a_file) {
struct stat st;
char real_filename[PATH_MAX + 1];
size_t real_filename_len = 0;
char *filename = NULL;
size_t filename_len = 0;
struct uwsgi_string_list *index = NULL;
if (!is_a_file) {
filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
filename_len = document_root_len + 1 + path_info_len;
}
else {
filename = uwsgi_concat2n(document_root, document_root_len, "", 0);
filename_len = document_root_len;
}
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
#endif
if (uwsgi.static_cache_paths) {
uwsgi_rlock(uwsgi.static_cache_paths->lock);
uint64_t item_len;
char *item = uwsgi_cache_get2(uwsgi.static_cache_paths, filename, filename_len, &item_len);
if (item && item_len > 0 && item_len <= PATH_MAX) {
memcpy(real_filename, item, item_len);
real_filename_len = item_len;
real_filename[real_filename_len] = 0;
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
goto found;
}
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
}
if (!realpath(filename, real_filename)) {
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
#endif
free(filename);
return -1;
}
real_filename_len = strlen(real_filename);
if (uwsgi.static_cache_paths) {
uwsgi_wlock(uwsgi.static_cache_paths->lock);
uwsgi_cache_set2(uwsgi.static_cache_paths, filename, filename_len, real_filename, real_filename_len, uwsgi.use_static_cache_paths, UWSGI_CACHE_FLAG_UPDATE);
uwsgi_rwunlock(uwsgi.static_cache_paths->lock);
}
found:
free(filename);
if (uwsgi_starts_with(real_filename, real_filename_len, document_root, document_root_len)) {
struct uwsgi_string_list *safe = uwsgi.static_safe;
while(safe) {
if (!uwsgi_starts_with(real_filename, real_filename_len, safe->value, safe->len)) {
goto safe;
}
safe = safe->next;
}
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s or a safe path\n", real_filename, document_root_len, document_root);
return -1;
}
safe:
if (!uwsgi_static_stat(wsgi_req, real_filename, &real_filename_len, &st, &index)) {
if (index) {
// if we are here the PATH_INFO need to be changed
if (uwsgi_req_append_path_info_with_index(wsgi_req, index->value, index->len)) {
return -1;
}
}
// skip methods other than GET and HEAD
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
return -1;
}
// check for skippable ext
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
while (sse) {
if (real_filename_len >= sse->len) {
if (!uwsgi_strncmp(real_filename + (real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
return -1;
}
}
sse = sse->next;
}
#ifdef UWSGI_ROUTING
// before sending the file, we need to check if some rule applies
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(uwsgi.routes, wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
return 0;
}
wsgi_req->routes_applied = 1;
#endif
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
}
return -1;
}
+3 -96
View File
@@ -13,7 +13,6 @@ struct uwsgi_stats *uwsgi_stats_new(size_t chunk_size) {
us->chunk = chunk_size;
us->size = chunk_size;
us->tabs = 1;
us->dirty = 0;
us->minified = uwsgi.stats_minified;
if (!us->minified) {
us->base[1] = '\n';
@@ -315,45 +314,6 @@ int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long l
return uwsgi_stats_comma(us);
}
int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
if (uwsgi_stats_apply_tabs(us))
return -1;
char *ptr = us->base + us->pos;
char *watermark = us->base + us->size;
size_t available = watermark - ptr;
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret < 0)
return -1;
while (ret >= (int) available) {
char *new_base = realloc(us->base, us->size + us->chunk);
if (!new_base)
return -1;
us->base = new_base;
us->size += us->chunk;
ptr = us->base + us->pos;
watermark = us->base + us->size;
available = watermark - ptr;
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
if (ret < 0)
return -1;
}
us->pos += ret;
return 0;
}
int uwsgi_stats_keyslong_comma(struct uwsgi_stats *us, char *key, long long num) {
int ret = uwsgi_stats_keyslong(us, key, num);
if (ret)
return -1;
return uwsgi_stats_comma(us);
}
void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
struct sockaddr_un client_src;
@@ -413,7 +373,7 @@ struct uwsgi_stats_pusher *uwsgi_stats_pusher_get(char *name) {
return usp;
}
struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *pusher, char *arg) {
struct uwsgi_stats_pusher_instance * uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *pusher, char *arg) {
struct uwsgi_stats_pusher_instance *old_uspi = NULL, *uspi = uwsgi.stats_pusher_instances;
while (uspi) {
old_uspi = uspi;
@@ -422,10 +382,7 @@ struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pu
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
uspi->pusher = pusher;
if (arg) {
uspi->arg = uwsgi_str(arg);
}
uspi->raw = pusher->raw;
uspi->arg = arg;
if (old_uspi) {
old_uspi->next = uspi;
}
@@ -464,8 +421,7 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
else {
if (!us) {
us = uwsgi_master_generate_stats();
if (!us)
goto next;
if (!us) goto next;
}
uspi->pusher->func(uspi, now, us->base, us->pos);
}
@@ -494,7 +450,6 @@ void uwsgi_stats_pusher_setup() {
pusher = uwsgi_stats_pusher_get(ssp);
if (!pusher) {
uwsgi_log("unable to find \"%s\" stats_pusher\n", ssp);
free(ssp);
exit(1);
}
char *arg = NULL;
@@ -504,7 +459,6 @@ void uwsgi_stats_pusher_setup() {
}
uwsgi_stats_pusher_add(pusher, arg);
usl = usl->next;
free(ssp);
}
}
@@ -574,50 +528,3 @@ void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t no
close(fd);
}
static void stats_dump_var(char *k, uint16_t kl, char *v, uint16_t vl, void *data) {
struct uwsgi_stats *us = (struct uwsgi_stats *) data;
if (us->dirty) return;
uint16_t i;
// replace " with '
for(i=0;i<kl;i++) {
if (k[i] == '"') {
k[i] = '\'';
}
}
for(i=0;i<vl;i++) {
if (v[i] == '"') {
v[i] = '\'';
}
}
char *var = uwsgi_concat3n(k, kl, "=", 1, v,vl);
if (uwsgi_stats_str(us, var)) {
us->dirty = 1;
free(var);
return;
}
free(var);
if (uwsgi_stats_comma(us)) {
us->dirty = 1;
}
return;
}
int uwsgi_stats_dump_vars(struct uwsgi_stats *us, struct uwsgi_core *uc) {
if (!uc->in_request) return 0;
struct uwsgi_header *uh = (struct uwsgi_header *) uwsgi.workers[0].cores[0].buffer;
uint16_t pktsize = uh->pktsize;
if (!pktsize) return 0;
char *dst = uwsgi.workers[0].cores[0].buffer;
memcpy(dst, uc->buffer+4, uwsgi.buffer_size);
// ok now check if something changed...
if (!uc->in_request) return 0;
if (uh->pktsize != pktsize) return 0;
if (memcmp(dst, uc->buffer+4, uwsgi.buffer_size)) return 0;
// nothing changed let's dump vars
int ret = uwsgi_hooked_parse(dst, pktsize, stats_dump_var, us);
if (ret) return -1;
if (us->dirty) return -1;
if (uwsgi_stats_str(us, "")) return -1;
return 0;
}
-47
View File
@@ -1,47 +0,0 @@
#include "../uwsgi.h"
/*
Storage subsystem: filesystem-like abstraction
struct uwsgi_storage_engine {
char *name;
uint16_t name_len;
int64_t (*get)(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t);
int64_t (*set)(char *, uint16_t, char *, uint64_t, uint64_t, uint64_t);
};
struct uwsgi_storage {
char *name;
uint16_t name_len;
struct uwsgi_storage_engine *engine;
};
*/
struct uwsgi_storage* uwsgi_storage_by_name(char *name, uint16_t name_len) {
if (!name_len) {
name_len = strlen(name);
}
struct uwsgi_storage *s = uwsgi.virtualdisks;
while(s) {
if (!uwsgi_strncmp(s->name, s->name_len, name, name_len)) {
return s;
}
s = s->next;
}
return NULL;
}
int64_t uwsgi_storage_get(struct uwsgi_storage *storage, char *key, uint16_t key_len, char *out_buf, uint64_t pos, uint64_t size, uint64_t flags) {
if (!storage->get) return -1;
return storage->get(key, key_len, out_buf, pos, size, flags);
}
int64_t uwsgi_storage_set(struct uwsgi_storage *storage, char *key, uint16_t key_len, char *in_buf, uint64_t pos, uint64_t size, uint64_t flags) {
if (!storage->set) return -1;
return storage->set(key, key_len, out_buf, pos, size, flags);
}
-340
View File
@@ -1,340 +0,0 @@
#include <uwsgi.h>
// check if a string_list contains an item
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *list, char *key, size_t keylen) {
struct uwsgi_string_list *usl = list;
while (usl) {
if (keylen == usl->len) {
if (!memcmp(key, usl->value, keylen)) {
return usl;
}
}
usl = usl->next;
}
return NULL;
}
// lower a string
char *uwsgi_lower(char *str, size_t size) {
size_t i;
for (i = 0; i < size; i++) {
str[i] = tolower((int) str[i]);
}
return str;
}
// check if a string is contained in another one
char *uwsgi_str_contains(char *str, int slen, char what) {
int i;
for (i = 0; i < slen; i++) {
if (str[i] == what) {
return str + i;
}
}
return NULL;
}
int uwsgi_contains_n(char *s1, size_t s1_len, char *s2, size_t s2_len) {
size_t i;
char *ptr = s2;
for (i = 0; i < s1_len; i++) {
if (s1[i] == *ptr) {
ptr++;
if (ptr == s2 + s2_len) {
return 1;
}
}
else {
ptr = s2;
}
}
return 0;
}
// fast compare 2 sized strings
int uwsgi_strncmp(char *src, int slen, char *dst, int dlen) {
if (slen != dlen)
return 1;
return memcmp(src, dst, dlen);
}
// fast compare 2 sized strings (case insensitive)
int uwsgi_strnicmp(char *src, int slen, char *dst, int dlen) {
if (slen != dlen)
return 1;
return strncasecmp(src, dst, dlen);
}
// fast sized check of initial part of a string
int uwsgi_starts_with(char *src, int slen, char *dst, int dlen) {
if (slen < dlen)
return -1;
return memcmp(src, dst, dlen);
}
// unsized check
int uwsgi_startswith(char *src, char *what, int wlen) {
int i;
for (i = 0; i < wlen; i++) {
if (src[i] != what[i])
return -1;
}
return 0;
}
// concatenate strings
char *uwsgi_concatn(int c, ...) {
va_list s;
char *item;
int j = c;
char *buf;
size_t len = 1;
size_t tlen = 1;
va_start(s, c);
while (j > 0) {
item = va_arg(s, char *);
if (item == NULL) {
break;
}
len += va_arg(s, int);
j--;
}
va_end(s);
buf = uwsgi_malloc(len);
memset(buf, 0, len);
j = c;
len = 0;
va_start(s, c);
while (j > 0) {
item = va_arg(s, char *);
if (item == NULL) {
break;
}
tlen = va_arg(s, int);
memcpy(buf + len, item, tlen);
len += tlen;
j--;
}
va_end(s);
return buf;
}
char *uwsgi_concat2(char *one, char *two) {
char *buf;
size_t len = strlen(one) + strlen(two) + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, strlen(one));
memcpy(buf + strlen(one), two, strlen(two));
return buf;
}
char *uwsgi_concat4(char *one, char *two, char *three, char *four) {
char *buf;
size_t len = strlen(one) + strlen(two) + strlen(three) + strlen(four) + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, strlen(one));
memcpy(buf + strlen(one), two, strlen(two));
memcpy(buf + strlen(one) + strlen(two), three, strlen(three));
memcpy(buf + strlen(one) + strlen(two) + strlen(three), four, strlen(four));
return buf;
}
char *uwsgi_concat3(char *one, char *two, char *three) {
char *buf;
size_t len = strlen(one) + strlen(two) + strlen(three) + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, strlen(one));
memcpy(buf + strlen(one), two, strlen(two));
memcpy(buf + strlen(one) + strlen(two), three, strlen(three));
return buf;
}
char *uwsgi_concat2n(char *one, int s1, char *two, int s2) {
char *buf;
size_t len = s1 + s2 + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, s1);
memcpy(buf + s1, two, s2);
return buf;
}
char *uwsgi_concat2nn(char *one, int s1, char *two, int s2, int *len) {
char *buf;
*len = s1 + s2 + 1;
buf = uwsgi_malloc(*len);
buf[*len - 1] = 0;
memcpy(buf, one, s1);
memcpy(buf + s1, two, s2);
return buf;
}
char *uwsgi_concat3n(char *one, int s1, char *two, int s2, char *three, int s3) {
char *buf;
size_t len = s1 + s2 + s3 + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, s1);
memcpy(buf + s1, two, s2);
memcpy(buf + s1 + s2, three, s3);
return buf;
}
char *uwsgi_concat4n(char *one, int s1, char *two, int s2, char *three, int s3, char *four, int s4) {
char *buf;
size_t len = s1 + s2 + s3 + s4 + 1;
buf = uwsgi_malloc(len);
buf[len - 1] = 0;
memcpy(buf, one, s1);
memcpy(buf + s1, two, s2);
memcpy(buf + s1 + s2, three, s3);
memcpy(buf + s1 + s2 + s3, four, s4);
return buf;
}
// concat unsized strings
char *uwsgi_concat(int c, ...) {
va_list s;
char *item;
size_t len = 1;
int j = c;
char *buf;
va_start(s, c);
while (j > 0) {
item = va_arg(s, char *);
if (item == NULL) {
break;
}
len += (int) strlen(item);
j--;
}
va_end(s);
buf = uwsgi_malloc(len);
memset(buf, 0, len);
j = c;
len = 0;
va_start(s, c);
while (j > 0) {
item = va_arg(s, char *);
if (item == NULL) {
break;
}
memcpy(buf + len, item, strlen(item));
len += strlen(item);
j--;
}
va_end(s);
return buf;
}
char *uwsgi_strncopy(char *s, int len) {
char *buf;
buf = uwsgi_malloc(len + 1);
buf[len] = 0;
memcpy(buf, s, len);
return buf;
}
// this move a string back of one char and put a 0 at the end (used in uwsgi parsers for buffer reusing)
char *uwsgi_cheap_string(char *buf, int len) {
int i;
char *cheap_buf = buf - 1;
for (i = 0; i < len; i++) {
*cheap_buf++ = buf[i];
}
buf[len - 1] = 0;
return buf - 1;
}
+176 -254
View File
@@ -91,7 +91,7 @@ static struct uwsgi_subscribe_node *uwsgi_subscription_algo_lrc(struct uwsgi_sub
if (min_rc == 0 || node->reference < min_rc) {
min_rc = node->reference;
choosen_node = node;
if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->last_requests <= node->last_requests))
if (min_rc == 0 && !(node->next && node->next->reference <= node->reference && node->next->requests <= node->requests))
break;
}
}
@@ -125,7 +125,7 @@ static struct uwsgi_subscribe_node *uwsgi_subscription_algo_wlrc(struct uwsgi_su
if (min_rc == 0 || ref < min_rc) {
min_rc = ref;
choosen_node = node;
if (min_rc == 0 && !(node->next && next_node_ref <= ref && node->next->last_requests <= node->last_requests))
if (min_rc == 0 && !(node->next && next_node_ref <= ref && node->next->requests <= node->requests))
break;
}
}
@@ -376,7 +376,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node->weight = usr->weight;
if (!node->weight)
node->weight = 1;
node->last_requests = 0;
return node;
}
old_node = node;
@@ -395,7 +394,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node->modifier1 = usr->modifier1;
node->modifier2 = usr->modifier2;
node->requests = 0;
node->last_requests = 0;
node->transferred = 0;
node->reference = 0;
node->death_mark = 0;
@@ -472,7 +470,6 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
current_slot->nodes->len = usr->address_len;
current_slot->nodes->reference = 0;
current_slot->nodes->requests = 0;
current_slot->nodes->last_requests = 0;
current_slot->nodes->transferred = 0;
current_slot->nodes->death_mark = 0;
current_slot->nodes->failcnt = 0;
@@ -517,8 +514,31 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
}
// TODO rewrite it using uwsgi buffers
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd, char *socket_name, char *sign) {
char value_cores[sizeof(UMAX64_STR) + 1];
char value_load[sizeof(UMAX64_STR) + 1];
char value_weight[sizeof(UMAX64_STR) + 1];
int value_cores_size = uwsgi_long2str2n(uwsgi.numproc * uwsgi.cores, value_cores, sizeof(UMAX64_STR));
int value_load_size = uwsgi_long2str2n(uwsgi.shared->load, value_load, sizeof(UMAX64_STR));
int value_weight_size = 0;
if (uwsgi.auto_weight) {
value_weight_size = uwsgi_long2str2n(uwsgi.numproc * uwsgi.cores, value_weight, sizeof(UMAX64_STR));
}
else {
value_weight_size = uwsgi_long2str2n(uwsgi.weight, value_weight, sizeof(UMAX64_STR));
}
char value_modifier1[4];
char value_modifier2[4];
int value_modifier1_size = uwsgi_long2str2n(modifier1, value_modifier1, 3);
int value_modifier2_size = uwsgi_long2str2n(modifier2, value_modifier2, 3);
if (socket_name == NULL && !uwsgi.sockets)
return;
@@ -526,44 +546,173 @@ void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8
socket_name = uwsgi.sockets->name;
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(socket_name)) + (2 + 9 + 2 + value_modifier1_size) + (2 + 9 + 2 + value_modifier2_size) + (2 + 5 + 2 + value_cores_size) + (2 + 4 + 2 + value_load_size) + (2 + 6 + 2 + value_weight_size);
// make space for uwsgi header
ub->pos = 4;
char *subscrbuf = uwsgi_malloc(ssb_size);
// leave space for uwsgi header
char *ssb = subscrbuf + 4;
if (uwsgi_buffer_append_keyval(ub, "key", 3, key, keysize)) goto end;
if (uwsgi_buffer_append_keyval(ub, "address", 7, socket_name, strlen(socket_name))) goto end;
if (uwsgi_buffer_append_keynum(ub, "modifier1", 9, modifier1)) goto end;
if (uwsgi_buffer_append_keynum(ub, "modifier2", 9, modifier2)) goto end;
if (uwsgi_buffer_append_keynum(ub, "cores", 5, uwsgi.numproc * uwsgi.cores)) goto end;
if (uwsgi_buffer_append_keynum(ub, "load", 4, uwsgi.shared->load)) goto end;
if (uwsgi.auto_weight) {
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.numproc * uwsgi.cores )) goto end;
}
else {
if (uwsgi_buffer_append_keynum(ub, "weight", 6, uwsgi.weight )) goto end;
}
// key = "domain"
uint16_t ustrlen = 3;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "key", ustrlen);
ssb += ustrlen;
ustrlen = keysize;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, key, ustrlen);
ssb += ustrlen;
// address = "first uwsgi socket"
ustrlen = 7;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "address", ustrlen);
ssb += ustrlen;
ustrlen = strlen(socket_name);
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, socket_name, ustrlen);
ssb += ustrlen;
// modifier1 = "modifier1"
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "modifier1", ustrlen);
ssb += ustrlen;
ustrlen = value_modifier1_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, value_modifier1, value_modifier1_size);
ssb += ustrlen;
// modifier2 = "modifier2"
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "modifier2", ustrlen);
ssb += ustrlen;
ustrlen = value_modifier2_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, value_modifier2, value_modifier2_size);
ssb += ustrlen;
// cores = uwsgi.numproc * uwsgi.cores
ustrlen = 5;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "cores", ustrlen);
ssb += ustrlen;
ustrlen = value_cores_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, value_cores, value_cores_size);
ssb += ustrlen;
// load
ustrlen = 4;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "load", ustrlen);
ssb += ustrlen;
ustrlen = value_load_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, value_load, value_load_size);
ssb += ustrlen;
// weight
ustrlen = 6;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "weight", ustrlen);
ssb += ustrlen;
ustrlen = value_weight_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, value_weight, value_weight_size);
ssb += ustrlen;
#ifdef UWSGI_SSL
if (sign) {
if (uwsgi_buffer_append_keynum(ub, "unix", 4, (uwsgi_now() + (time_t) cmd) )) goto end;
// add space for "unix" item
char unix_dst[sizeof(UMAX64_STR) + 1];
if (snprintf(unix_dst, sizeof(UMAX64_STR) + 1, "%lu", (unsigned long) (uwsgi_now() + (time_t) cmd)) < 1) {
uwsgi_error("unable to generate unix time for subscription !!!\n");
free(subscrbuf);
return;
}
ssb_size += 2 + 4 + 2 + strlen(unix_dst);
char *new_buf = realloc(subscrbuf, ssb_size);
if (!new_buf) {
uwsgi_error("realloc()");
free(subscrbuf);
return;
}
// fix ssb (new_buf base could be changed)
ssb = (new_buf + (ssb - subscrbuf));
subscrbuf = new_buf;
ustrlen = 4;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "unix", ustrlen);
ssb += ustrlen;
ustrlen = strlen(unix_dst);
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, unix_dst, strlen(unix_dst));
ssb += ustrlen;
unsigned int signature_len = 0;
char *signature = uwsgi_rsa_sign(sign, ub->buf + 4, ub->pos - 4, &signature_len);
char *signature = uwsgi_rsa_sign(sign, subscrbuf + 4, ssb_size - 4, &signature_len);
if (signature && signature_len > 0) {
if (uwsgi_buffer_append_keyval(ub, "sign", 4, signature, signature_len)) {
// add space for "sign" item
ssb_size += 2 + 4 + 2 + signature_len;
char *new_buf = realloc(subscrbuf, ssb_size);
if (!new_buf) {
uwsgi_error("realloc()");
free(signature);
goto end;
free(subscrbuf);
return;
}
// fix ssb (new_buf base could be changed)
ssb = (new_buf + (ssb - subscrbuf));
subscrbuf = new_buf;
ustrlen = 4;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, "sign", ustrlen);
ssb += ustrlen;
ustrlen = signature_len;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ssb, signature, signature_len);
ssb += ustrlen;
free(signature);
}
}
#endif
send_udp_message(224, cmd, udp_address, ub->buf, ub->pos - 4);
end:
uwsgi_buffer_destroy(ub);
send_udp_message(224, cmd, udp_address, subscrbuf, ssb_size - 4);
free(subscrbuf);
}
@@ -607,230 +756,3 @@ struct uwsgi_subscribe_slot **uwsgi_subscription_init_ht() {
}
return uwsgi_calloc(sizeof(struct uwsgi_subscription_slot *) * UMAX16);
}
void uwsgi_subscribe(char *subscription, uint8_t cmd) {
size_t subfile_size;
size_t i;
char *key = NULL;
int keysize = 0;
char *modifier1 = NULL;
int modifier1_len = 0;
char *socket_name = NULL;
char *udp_address = subscription;
char *udp_port = NULL;
char *subscription_key = NULL;
char *sign = NULL;
// check for explicit socket_name
char *equal = strchr(subscription, '=');
if (equal) {
socket_name = subscription;
if (socket_name[0] == '=') {
equal = strchr(socket_name + 1, '=');
if (!equal)
return;
*equal = '\0';
struct uwsgi_socket *us = uwsgi_get_shared_socket_by_num(atoi(socket_name + 1));
if (!us)
return;
socket_name = us->name;
}
*equal = '\0';
udp_address = equal + 1;
}
// check for unix socket
if (udp_address[0] != '/') {
udp_port = strchr(udp_address, ':');
if (!udp_port) {
if (equal)
*equal = '=';
return;
}
subscription_key = strchr(udp_port + 1, ':');
}
else {
subscription_key = strchr(udp_address + 1, ':');
}
if (!subscription_key) {
if (equal)
*equal = '=';
return;
}
udp_address = uwsgi_concat2n(udp_address, subscription_key - udp_address, "", 0);
if (subscription_key[1] == '@') {
if (!uwsgi_file_exists(subscription_key + 2))
goto clear;
char *lines = uwsgi_open_and_read(subscription_key + 2, &subfile_size, 1, NULL);
if (subfile_size > 0) {
key = lines;
for (i = 0; i < subfile_size; i++) {
if (lines[i] == 0) {
if (keysize > 0) {
if (key[0] != '#' && key[0] != '\n') {
modifier1 = strchr(key, ',');
if (modifier1) {
modifier1[0] = 0;
modifier1++;
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
modifier1 = NULL;
modifier1_len = 0;
}
}
break;
}
else if (lines[i] == '\n') {
if (keysize > 0) {
if (key[0] != '#' && key[0] != '\n') {
lines[i] = 0;
modifier1 = strchr(key, ',');
if (modifier1) {
modifier1[0] = 0;
modifier1++;
modifier1_len = strlen(modifier1);
keysize = strlen(key);
}
uwsgi_send_subscription(udp_address, key, keysize, uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
modifier1 = NULL;
modifier1_len = 0;
lines[i] = '\n';
}
}
key = lines + i + 1;
keysize = 0;
continue;
}
keysize++;
}
free(lines);
}
}
else {
modifier1 = strchr(subscription_key + 1, ',');
if (modifier1) {
modifier1[0] = 0;
modifier1++;
sign = strchr(modifier1 + 1, ',');
if (sign) {
*sign = 0;
sign++;
}
modifier1_len = strlen(modifier1);
}
uwsgi_send_subscription(udp_address, subscription_key + 1, strlen(subscription_key + 1), uwsgi_str_num(modifier1, modifier1_len), 0, cmd, socket_name, sign);
if (modifier1)
modifier1[-1] = ',';
if (sign)
sign[-1] = ',';
}
clear:
if (equal)
*equal = '=';
free(udp_address);
}
void uwsgi_subscribe2(char *arg, uint8_t cmd) {
char *s2_server = NULL;
char *s2_key = NULL;
char *s2_socket = NULL;
char *s2_addr = NULL;
char *s2_weight = NULL;
char *s2_sign = NULL;
char *s2_modifier1 = NULL;
char *s2_modifier2 = NULL;
char *s2_check = NULL;
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
"server", &s2_server,
"key", &s2_key,
"socket", &s2_socket,
"addr", &s2_addr,
"weight", &s2_weight,
"modifier1", &s2_modifier1,
"modifier2", &s2_modifier2,
"sign", &s2_sign,
"check", &s2_check,
NULL)) {
return;
}
if (!s2_server || !s2_key) goto end;
if (s2_check) {
if (uwsgi_file_exists(s2_check)) goto end;
}
if (s2_weight) {
uwsgi.weight = atoi(s2_weight);
}
if (s2_socket) {
struct uwsgi_socket *us = uwsgi_get_socket_by_num(atoi(s2_socket));
if (us) {
if (s2_addr) {
free(s2_addr);
}
s2_addr = uwsgi_str(us->name);
}
}
uint8_t modifier1 = 0;
uint8_t modifier2 = 0;
if (s2_modifier1) {
modifier1 = atoi(s2_modifier1);
}
if (s2_modifier2) {
modifier2 = atoi(s2_modifier2);
}
uwsgi_send_subscription(s2_server, s2_key, strlen(s2_key), modifier1, modifier2, cmd, s2_addr, s2_sign);
end:
if (s2_server) free(s2_server);
if (s2_key) free(s2_key);
if (s2_socket) free(s2_socket);
if (s2_addr) free(s2_addr);
if (s2_weight) free(s2_weight);
if (s2_modifier1) free(s2_modifier1);
if (s2_modifier2) free(s2_modifier2);
if (s2_sign) free(s2_sign);
if (s2_check) free(s2_check);
}
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
// -- subscribe
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
while (subscriptions) {
if (verbose) {
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
}
uwsgi_subscribe(subscriptions->value, cmd);
subscriptions = subscriptions->next;
}
// --subscribe2
subscriptions = uwsgi.subscriptions2;
while (subscriptions) {
if (verbose) {
uwsgi_log("%s %s\n", cmd ? "unsubscribing from" : "subscribing to", subscriptions->value);
}
uwsgi_subscribe2(subscriptions->value, cmd);
subscriptions = subscriptions->next;
}
}
-56
View File
@@ -1,56 +0,0 @@
#include <uwsgi.h>
/*
uWSGI timebomb
this is a simple thread waiting for a timeout and calling exit
with the specified value.
You can use it as a last resort in async apps that could block
normal uWSGI behaviours
*/
struct time_bomb {
int timeout;
int exit_code;
};
static void *time_bomb(void *arg) {
// block all signals
sigset_t smask;
sigfillset(&smask);
pthread_sigmask(SIG_BLOCK, &smask, NULL);
struct time_bomb *tb = (struct time_bomb *) arg;
struct timeval tv;
tv.tv_sec = tb->timeout;
tv.tv_usec = 0;
select(0, NULL, NULL, NULL, &tv);
uwsgi_log_verbose("*** BOOOOOOM ***\n");
exit(tb->exit_code);
}
void uwsgi_time_bomb(int timeout, int exit_code) {
pthread_t time_bomb_thread;
struct time_bomb *tb = uwsgi_malloc(sizeof(struct time_bomb));
tb->timeout = timeout;
tb->exit_code = exit_code;
if (pthread_create(&time_bomb_thread, NULL, time_bomb, (void *) tb)) {
uwsgi_error("pthread_create()");
uwsgi_log("unable to setup the time bomb, goodbye\n");
exit(exit_code);
}
else {
uwsgi_log_verbose("Fire in the hole !!! (%d seconds to detonation)\n", timeout);
}
}
-166
View File
@@ -1,166 +0,0 @@
#include <uwsgi.h>
/*
uWSGI transformations
each body chunk is passed (in chain) to every transformation
some of them supports streaming, other requires buffering
at the end of the request the "final chain" is called (and the whole chain freed)
Transformations (if required) could completely swallow already set headers
*/
extern struct uwsgi_server uwsgi;
// -1 error, 0 = no buffer, send the body, 1 = buffer
int uwsgi_apply_transformations(struct wsgi_request *wsgi_req, char *buf, size_t len) {
wsgi_req->transformed_chunk = NULL;
wsgi_req->transformed_chunk_len = 0;
struct uwsgi_transformation *ut = wsgi_req->transformations;
char *t_buf = buf;
size_t t_len = len;
uint8_t flushed = 0;
while(ut) {
// allocate the buffer (if needed)
if (!ut->chunk) {
ut->chunk = uwsgi_buffer_new(t_len);
}
// skip final transformations before appending data
if (ut->is_final) goto next;
if (uwsgi_buffer_append(ut->chunk, t_buf, t_len)) {
return -1;
}
// if the transformation cannot stream, continue buffering (the func will be called at the end)
if (!ut->can_stream) return 1;
ut->round++;
if (ut->func(wsgi_req, ut)) {
return -1;
}
if (ut->flushed) flushed = 1;
t_buf = ut->chunk->buf;
t_len = ut->chunk->pos;
// we reset the buffer, so we do not waste memory
ut->chunk->pos = 0;
next:
ut = ut->next;
}
// if we are here we can tell the writer to send the body to the client
// no buffering please
if (!flushed) {
wsgi_req->transformed_chunk = t_buf;
wsgi_req->transformed_chunk_len = t_len;
}
return 0;
}
/*
run all the remaining (or buffered) transformations
*/
int uwsgi_apply_final_transformations(struct wsgi_request *wsgi_req) {
struct uwsgi_transformation *ut = wsgi_req->transformations;
wsgi_req->transformed_chunk = NULL;
wsgi_req->transformed_chunk_len = 0;
char *t_buf = NULL;
size_t t_len = 0;
uint8_t flushed = 0;
int found_nostream = 0;
while(ut) {
if (!found_nostream) {
if (!ut->can_stream) {
found_nostream = 1;
}
else {
t_buf = ut->chunk->buf;
t_len = ut->chunk->pos;
goto next;
}
}
if (!ut->chunk) {
if (t_len > 0) {
ut->chunk = uwsgi_buffer_new(t_len);
}
else {
ut->chunk = uwsgi_buffer_new(uwsgi.page_size);
}
}
if (t_len > 0) {
if (uwsgi_buffer_append(ut->chunk, t_buf, t_len)) {
return -1;
}
}
// run the transformation
ut->round++;
if (ut->func(wsgi_req, ut)) {
return -1;
}
if (ut->flushed) flushed = 1;
t_buf = ut->chunk->buf;
t_len = ut->chunk->pos;
next:
ut = ut->next;
}
// if we are here, all of the transformations are applied
if (!flushed) {
wsgi_req->transformed_chunk = t_buf;
wsgi_req->transformed_chunk_len = t_len;
}
return 0;
}
void uwsgi_free_transformations(struct wsgi_request *wsgi_req) {
struct uwsgi_transformation *ut = wsgi_req->transformations;
while(ut) {
struct uwsgi_transformation *current_ut = ut;
if (current_ut->chunk) {
uwsgi_buffer_destroy(current_ut->chunk);
}
if (current_ut->ub) {
uwsgi_buffer_destroy(current_ut->ub);
}
if (current_ut->fd > -1) {
close(current_ut->fd);
}
ut = ut->next;
free(current_ut);
}
}
struct uwsgi_transformation *uwsgi_add_transformation(struct wsgi_request *wsgi_req, int (*func)(struct wsgi_request *, struct uwsgi_transformation *), void *data) {
struct uwsgi_transformation *old_ut = NULL, *ut = wsgi_req->transformations;
while(ut) {
old_ut = ut;
ut = ut->next;
}
ut = uwsgi_calloc(sizeof(struct uwsgi_transformation));
ut->func = func;
ut->fd = -1;
ut->data = data;
if (old_ut) {
old_ut->next = ut;
}
else {
wsgi_req->transformations = ut;
}
return ut;
}
+1855 -726
View File
File diff suppressed because it is too large Load Diff
+409 -595
View File
File diff suppressed because it is too large Load Diff
-359
View File
@@ -1,359 +0,0 @@
#include "uwsgi.h"
/*
uWSGI websockets functions
sponsored by 20Tab S.r.l. <info@20tab.com>
*/
extern struct uwsgi_server uwsgi;
static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(10 + len);
if (uwsgi_buffer_u8(ub, 0x81)) goto error;
if (len < 126) {
if (uwsgi_buffer_u8(ub, len)) goto error;
}
else if (len <= (uint16_t) 0xffff) {
if (uwsgi_buffer_u8(ub, 126)) goto error;
if (uwsgi_buffer_u16be(ub, len)) goto error;
}
else {
if (uwsgi_buffer_u8(ub, 127)) goto error;
if (uwsgi_buffer_u64be(ub, len)) goto error;
}
if (uwsgi_buffer_append(ub, msg, len)) goto error;
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
static int uwsgi_websockets_ping(struct wsgi_request *wsgi_req) {
if (uwsgi_response_write_body_do(wsgi_req, uwsgi.websockets_ping->buf, uwsgi.websockets_ping->pos)) {
return -1;
}
wsgi_req->websocket_last_ping = uwsgi_now();
return 0;
}
static int uwsgi_websockets_pong(struct wsgi_request *wsgi_req) {
return uwsgi_response_write_body_do(wsgi_req, uwsgi.websockets_pong->buf, uwsgi.websockets_pong->pos);
}
static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
time_t now = uwsgi_now();
// first round
if (wsgi_req->websocket_last_ping == 0) {
return uwsgi_websockets_ping(wsgi_req);
}
// pong not received ?
if (wsgi_req->websocket_last_pong < wsgi_req->websocket_last_ping) {
if (wsgi_req->websocket_last_ping - wsgi_req->websocket_last_pong > uwsgi.websockets_pong_tolerance) {
uwsgi_log("[uwsgi-websocket] no PONG received in %d seconds !!!\n", uwsgi.websockets_pong_tolerance);
return -1;
}
return 0;
}
// pong received, send anther ping
if (now - wsgi_req->websocket_last_ping >= uwsgi.websockets_ping_freq) {
return uwsgi_websockets_ping(wsgi_req);
}
return 0;
}
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len) {
struct uwsgi_buffer *ub = uwsgi_websocket_message(msg, len);
if (!ub) return -1;
ssize_t ret = uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
uwsgi_buffer_destroy(ub);
return ret;
}
int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) {
if (wsgi_req->websocket_closed) {
return -1;
}
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len);
if (ret < 0) {
wsgi_req->websocket_closed = 1;
}
return ret;
}
static void uwsgi_websocket_parse_header(struct wsgi_request *wsgi_req) {
uint8_t byte1 = wsgi_req->websocket_buf->buf[0];
uint8_t byte2 = wsgi_req->websocket_buf->buf[1];
wsgi_req->websocket_opcode = byte1 & 0xf;
wsgi_req->websocket_has_mask = byte2 >> 7;
wsgi_req->websocket_size = byte2 & 0x7f;
}
static struct uwsgi_buffer *uwsgi_websockets_parse(struct wsgi_request *wsgi_req) {
// de-mask buffer
uint8_t *ptr = (uint8_t *) (wsgi_req->websocket_buf->buf + (wsgi_req->websocket_pktsize - wsgi_req->websocket_size));
size_t i;
if (wsgi_req->websocket_has_mask) {
uint8_t *mask = ptr-4;
for(i=0;i<wsgi_req->websocket_size;i++) {
ptr[i] = ptr[i] ^ mask[i%4];
}
}
struct uwsgi_buffer *ub = uwsgi_buffer_new(wsgi_req->websocket_size);
if (uwsgi_buffer_append(ub, (char *) ptr, wsgi_req->websocket_size)) goto error;
if (uwsgi_buffer_decapitate(wsgi_req->websocket_buf, wsgi_req->websocket_pktsize)) goto error;
wsgi_req->websocket_phase = 0;
wsgi_req->websocket_need = 2;
return ub;
error:
uwsgi_buffer_destroy(ub);
return NULL;
}
static ssize_t uwsgi_websockets_recv_pkt(struct wsgi_request *wsgi_req, int nb) {
int ret = -1;
for(;;) {
ssize_t rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->websocket_buf->buf + wsgi_req->websocket_buf->pos, wsgi_req->websocket_buf->len - wsgi_req->websocket_buf->pos);
if (rlen > 0) return rlen;
if (rlen == 0) return -1;
if (rlen < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
if (nb) {
if (uwsgi_websockets_check_pingpong(wsgi_req)) {
return -1;
}
return 0;
}
goto wait;
}
uwsgi_error("uwsgi_websockets_recv_pkt()");
return -1;
}
wait:
ret = uwsgi.wait_read_hook(wsgi_req->fd, uwsgi.websockets_ping_freq);
if (ret > 0) {
rlen = wsgi_req->socket->proto_read_body(wsgi_req, wsgi_req->websocket_buf->buf + wsgi_req->websocket_buf->pos, wsgi_req->websocket_buf->len - wsgi_req->websocket_buf->pos);
if (rlen > 0) return rlen;
if (rlen <= 0) return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_websockets_recv_pkt()");
return -1;
}
// send unsolicited pong
if (uwsgi_websockets_check_pingpong(wsgi_req)) {
return -1;
}
}
return -1;
}
static struct uwsgi_buffer *uwsgi_websocket_recv_do(struct wsgi_request *wsgi_req, int nb) {
if (!wsgi_req->websocket_buf) {
// this buffer will be destroyed on connection close
wsgi_req->websocket_buf = uwsgi_buffer_new(uwsgi.page_size);
// need 2 byte header
wsgi_req->websocket_need = 2;
}
for(;;) {
size_t remains = wsgi_req->websocket_buf->pos;
// i have data;
if (remains >= wsgi_req->websocket_need) {
switch(wsgi_req->websocket_phase) {
// header
case 0:
uwsgi_websocket_parse_header(wsgi_req);
wsgi_req->websocket_pktsize = 2 + (wsgi_req->websocket_has_mask*4);
if (wsgi_req->websocket_size == 126) {
wsgi_req->websocket_need += 2;
wsgi_req->websocket_phase = 1;
wsgi_req->websocket_pktsize += 2;
}
else if (wsgi_req->websocket_size == 127) {
wsgi_req->websocket_need += 8;
wsgi_req->websocket_phase = 1;
wsgi_req->websocket_pktsize += 8;
}
else {
wsgi_req->websocket_phase = 2;
}
break;
// size
case 1:
if (wsgi_req->websocket_size == 126) {
wsgi_req->websocket_size = uwsgi_be16(wsgi_req->websocket_buf->buf+2);
}
else if (wsgi_req->websocket_size == 127) {
wsgi_req->websocket_size = uwsgi_be64(wsgi_req->websocket_buf->buf+2);
}
else {
uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n");
return NULL;
}
if (wsgi_req->websocket_size > (uwsgi.websockets_max_size*1024)) {
uwsgi_log("[uwsgi-websocket] invalid packet size received: %llu, max allowed: %llu\n", wsgi_req->websocket_size, uwsgi.websockets_max_size * 1024);
return NULL;
}
wsgi_req->websocket_phase = 2;
break;
// mask check
case 2:
if (wsgi_req->websocket_has_mask) {
wsgi_req->websocket_need += 4;
wsgi_req->websocket_phase = 3;
}
else {
wsgi_req->websocket_need += wsgi_req->websocket_size;
wsgi_req->websocket_phase = 4;
}
break;
// mask
case 3:
wsgi_req->websocket_pktsize += wsgi_req->websocket_size;
wsgi_req->websocket_need += wsgi_req->websocket_size;
wsgi_req->websocket_phase = 4;
break;
// message
case 4:
switch (wsgi_req->websocket_opcode) {
// message
case 0:
case 1:
case 2:
return uwsgi_websockets_parse(wsgi_req);
// close
case 0x8:
return NULL;
// ping
case 0x9:
if (uwsgi_websockets_pong(wsgi_req)) {
return NULL;
}
break;
// pong
case 0xA:
wsgi_req->websocket_last_pong = uwsgi_now();
break;
default:
break;
}
// reset the status
wsgi_req->websocket_phase = 0;
wsgi_req->websocket_need = 2;
// decapitate the buffer
if (uwsgi_buffer_decapitate(wsgi_req->websocket_buf, wsgi_req->websocket_pktsize)) return NULL;
break;
// oops
default:
uwsgi_log("[uwsgi-websocket] BUG error in websocket parser\n");
return NULL;
}
}
// need more data
else {
if (uwsgi_buffer_ensure(wsgi_req->websocket_buf, uwsgi.page_size)) return NULL;
ssize_t len = uwsgi_websockets_recv_pkt(wsgi_req, nb);
if (len <= 0) {
if (nb == 1 && len == 0) {
// return an empty buffer to signal blocking event
return uwsgi_buffer_new(0);
}
return NULL;
}
// update buffer size
wsgi_req->websocket_buf->pos+=len;
}
}
return NULL;
}
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *wsgi_req) {
if (wsgi_req->websocket_closed) {
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_websocket_recv_do(wsgi_req, 0);
if (!ub) {
wsgi_req->websocket_closed = 1;
}
return ub;
}
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *wsgi_req) {
if (wsgi_req->websocket_closed) {
return NULL;
}
struct uwsgi_buffer *ub = uwsgi_websocket_recv_do(wsgi_req, 1);
if (!ub) {
wsgi_req->websocket_closed = 1;
}
return ub;
}
ssize_t uwsgi_websockets_simple_send(struct wsgi_request *wsgi_req, struct uwsgi_buffer *ub) {
ssize_t len = wsgi_req->socket->proto_write(wsgi_req, ub->buf, ub->pos);
if (wsgi_req->write_errors > 0) {
return -1;
}
return len;
}
int uwsgi_websocket_handshake(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *origin, uint16_t origin_len) {
#ifdef UWSGI_SSL
char sha1[20];
if (uwsgi_response_prepare_headers(wsgi_req, "101 Web Socket Protocol Handshake", 33)) return -1;
if (uwsgi_response_add_header(wsgi_req, "Upgrade", 7, "WebSocket", 9)) return -1;
if (uwsgi_response_add_header(wsgi_req, "Connection", 10, "Upgrade", 7)) return -1;
if (origin_len > 0) {
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, origin, origin_len)) return -1;
}
else {
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Origin", 20, "*", 1)) return -1;
}
// generate websockets sha1 and encode it to base64
if (!uwsgi_sha1_2n(key, key_len, "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", 36, sha1)) return -1;
size_t b64_len = 0;
char *b64 = uwsgi_base64_encode(sha1, 20, &b64_len);
if (!b64) return -1;
if (uwsgi_response_add_header(wsgi_req, "Sec-WebSocket-Accept", 20, b64, b64_len)) {
free(b64);
return -1;
}
free(b64);
wsgi_req->websocket_last_pong = uwsgi_now();
return uwsgi_response_write_headers_do(wsgi_req);
#else
uwsgi_log("you need to build uWSGI with SSL support to use the websocket handshake api function !!!\n");
return -1;
#endif
}
void uwsgi_websockets_init() {
uwsgi.websockets_pong = uwsgi_buffer_new(2);
uwsgi_buffer_append(uwsgi.websockets_pong, "\x8A\0", 2);
uwsgi.websockets_ping = uwsgi_buffer_new(2);
uwsgi_buffer_append(uwsgi.websockets_ping, "\x89\0", 2);
uwsgi.websockets_ping_freq = 30;
uwsgi.websockets_pong_tolerance = 3;
uwsgi.websockets_max_size = 1024;
}
-442
View File
@@ -1,442 +0,0 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
int uwsgi_response_add_content_length(struct wsgi_request *wsgi_req, uint64_t cl) {
char buf[sizeof(UMAX64_STR)+1];
int ret = snprintf(buf, sizeof(UMAX64_STR)+1, "%llu", (unsigned long long) cl);
if (ret <= 0 || ret > (int) (sizeof(UMAX64_STR)+1)) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, "Content-Length", 14, buf, ret);
}
int uwsgi_response_add_expires(struct wsgi_request *wsgi_req, uint64_t t) {
// 30+1
char expires[31];
int len = uwsgi_http_date((time_t) t, expires);
if (!len) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, "Expires", 7, expires, len);
}
int uwsgi_response_add_date(struct wsgi_request *wsgi_req, char *hkey, uint16_t hlen, uint64_t t) {
// 30+1
char d[31];
int len = uwsgi_http_date((time_t) t, d);
if (!len) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, hkey, hlen, d, len);
}
int uwsgi_response_add_last_modified(struct wsgi_request *wsgi_req, uint64_t t) {
// 30+1
char lm[31];
int len = uwsgi_http_date((time_t) t, lm);
if (!len) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, "Last-Modified", 13, lm, len);
}
int uwsgi_response_add_content_range(struct wsgi_request *wsgi_req, uint64_t start, uint64_t end, uint64_t cl) {
char buf[6+(sizeof(UMAX64_STR)*3)+4];
if (end == 0) {
end = cl-1;
}
int ret = snprintf(buf, 6+(sizeof(UMAX64_STR)*3)+4, "bytes %llu-%llu/%llu", (unsigned long long) start, (unsigned long long) end, (unsigned long long) cl);
if (ret <= 0 || ret > (int) (6+(sizeof(UMAX64_STR)*3)+4)) {
wsgi_req->write_errors++;
return -1;
}
return uwsgi_response_add_header(wsgi_req, "Content-Range", 13, buf, ret);
}
int uwsgi_response_prepare_headers_int(struct wsgi_request *wsgi_req, int status) {
char status_str[11];
uwsgi_num2str2(status, status_str);
return uwsgi_response_prepare_headers(wsgi_req, status_str, 3);
}
// status could be NNN or NNN message
int uwsgi_response_prepare_headers(struct wsgi_request *wsgi_req, char *status, uint16_t status_len) {
if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || status_len < 3 || wsgi_req->write_errors) return -1;
if (!wsgi_req->headers) {
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->headers->limit = UMAX16;
}
// reset the buffer (could be useful for rollbacks...)
wsgi_req->headers->pos = 0;
// reset headers count
wsgi_req->header_cnt = 0;
struct uwsgi_buffer *hh = NULL;
wsgi_req->status = uwsgi_str3_num(status);
#ifdef UWSGI_ROUTING
// apply error routes
if (uwsgi_apply_error_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
// from now on ignore write body requests...
wsgi_req->ignore_body = 1;
return -1;
}
wsgi_req->is_error_routing = 0;
#endif
if (status_len <= 4) {
char *new_sc = NULL;
size_t new_sc_len = 0;
uint16_t sc_len = 0;
const char *sc = uwsgi_http_status_msg(status, &sc_len);
if (sc) {
new_sc = uwsgi_concat3n(status, 3, " ", 1, (char *)sc, sc_len);
new_sc_len = 4+sc_len;
}
else {
new_sc = uwsgi_concat2n(status, 3, " Unknown", 8);
new_sc_len = 11;
}
hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, new_sc, new_sc_len);
free(new_sc);
}
else {
hh = wsgi_req->socket->proto_prepare_headers(wsgi_req, status, status_len);
}
if (!hh) {wsgi_req->write_errors++; return -1;}
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
uwsgi_buffer_destroy(hh);
return 0;
error:
uwsgi_buffer_destroy(hh);
wsgi_req->write_errors++;
return -1;
}
//each protocol has its header generator
static int uwsgi_response_add_header_do(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
if (!wsgi_req->headers) {
wsgi_req->headers = uwsgi_buffer_new(uwsgi.page_size);
wsgi_req->headers->limit = UMAX16;
}
struct uwsgi_buffer *hh = wsgi_req->socket->proto_add_header(wsgi_req, key, key_len, value, value_len);
if (!hh) { wsgi_req->write_errors++ ; return -1;}
if (uwsgi_buffer_append(wsgi_req->headers, hh->buf, hh->pos)) goto error;
wsgi_req->header_cnt++;
uwsgi_buffer_destroy(hh);
return 0;
error:
uwsgi_buffer_destroy(hh);
wsgi_req->write_errors++;
return -1;
}
int uwsgi_response_add_header(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || wsgi_req->write_errors) return -1;
struct uwsgi_string_list *rh = uwsgi.remove_headers;
while(rh) {
if (!uwsgi_strnicmp(key, key_len, rh->value, rh->len)) {
return 0;
}
rh = rh->next;
}
rh = wsgi_req->remove_headers;
while(rh) {
if (!uwsgi_strnicmp(key, key_len, rh->value, rh->len)) {
return 0;
}
rh = rh->next;
}
return uwsgi_response_add_header_do(wsgi_req, key, key_len, value, value_len);
}
int uwsgi_response_add_header_force(struct wsgi_request *wsgi_req, char *key, uint16_t key_len, char *value, uint16_t value_len) {
if (wsgi_req->headers_sent || wsgi_req->headers_size || wsgi_req->response_size || wsgi_req->write_errors) return -1;
return uwsgi_response_add_header_do(wsgi_req, key, key_len, value, value_len);
}
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
if (wsgi_req->headers_sent || !wsgi_req->headers || wsgi_req->response_size || wsgi_req->write_errors) {
return UWSGI_OK;
}
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
ah = ah->next;
}
ah = wsgi_req->additional_headers;
while(ah) {
if (uwsgi_response_add_header(wsgi_req, NULL, 0, ah->value, ah->len)) return -1;
ah = ah->next;
}
if (wsgi_req->socket->proto_fix_headers(wsgi_req)) { wsgi_req->write_errors++ ; return -1;}
for(;;) {
int ret = wsgi_req->socket->proto_write_headers(wsgi_req, wsgi_req->headers->buf, wsgi_req->headers->pos);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_response_write_headers_do()");
}
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_response_write_headers_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
wsgi_req->headers_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
wsgi_req->headers_sent = 1;
return UWSGI_OK;
}
// this is the function called by all request plugins to send chunks to the client
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
if (wsgi_req->write_errors) return -1;
if (wsgi_req->ignore_body) return UWSGI_OK;
// if the transformation chain returns 1, we are in buffering mode
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
int t_ret = uwsgi_apply_transformations(wsgi_req, buf, len);
if (t_ret == 0) {
buf = wsgi_req->transformed_chunk;
len = wsgi_req->transformed_chunk_len;
// reset transformation
wsgi_req->transformed_chunk = NULL;
wsgi_req->transformed_chunk_len = 0;
goto write;
}
if (t_ret == 1) {
return UWSGI_OK;
}
wsgi_req->write_errors++;
return -1;
}
write:
// send headers if not already sent
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendbody;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
wsgi_req->write_errors++;
return -1;
}
sendbody:
if (len == 0) return UWSGI_OK;
for(;;) {
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_response_write_body_do()");
}
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_response_write_body_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
wsgi_req->response_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
return UWSGI_OK;
}
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
return uwsgi_response_sendfile_do_can_close(wsgi_req, fd, pos, len, 1);
}
int uwsgi_response_sendfile_do_can_close(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len, int can_close) {
if (fd == wsgi_req->sendfile_fd) can_close = 0;
if (wsgi_req->write_errors) {
if (can_close) close(fd);
return -1;
}
if (wsgi_req->ignore_body) {
if (can_close) close(fd);
return UWSGI_OK;
}
if (!wsgi_req->headers_sent) {
int ret = uwsgi_response_write_headers_do(wsgi_req);
if (ret == UWSGI_OK) goto sendfile;
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
sendfile:
if (len == 0) {
struct stat st;
if (fstat(fd, &st)) {
uwsgi_error("uwsgi_response_sendfile_do()/fstat()");
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
if (pos >= (size_t)st.st_size) {
if (can_close) close(fd);
return UWSGI_OK;
}
len = st.st_size;
}
if (wsgi_req->socket->can_offload) {
// of we cannot close the socket (before the app will close it later)
// let's dup it
if (!can_close) {
int tmp_fd = dup(fd);
if (tmp_fd < 0) {
uwsgi_error("uwsgi_response_sendfile_do()/dup()");
wsgi_req->write_errors++;
return -1;
}
fd = tmp_fd;
can_close = 1;
}
if (!uwsgi_offload_request_sendfile_do(wsgi_req, fd, len)) {
wsgi_req->via = UWSGI_VIA_OFFLOAD;
wsgi_req->response_size += len;
return 0;
}
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
wsgi_req->via = UWSGI_VIA_SENDFILE;
for(;;) {
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_response_sendfile_do()");
}
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
if (ret == UWSGI_OK) {
break;
}
ret = uwsgi_wait_write_req(wsgi_req);
if (ret < 0) {
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
if (ret == 0) {
uwsgi_log("uwsgi_response_sendfile_do() TIMEOUT !!!\n");
wsgi_req->write_errors++;
if (can_close) close(fd);
return -1;
}
}
wsgi_req->response_size += wsgi_req->write_pos;
// reset for the next write
wsgi_req->write_pos = 0;
// close the file descriptor
if (can_close) close(fd);
return UWSGI_OK;
}
int uwsgi_simple_wait_write_hook(int fd, int timeout) {
struct pollfd upoll;
timeout = timeout * 1000;
upoll.fd = fd;
upoll.events = POLLOUT;
upoll.revents = 0;
int ret = poll(&upoll, 1, timeout);
if (ret > 0) {
if (upoll.revents & POLLOUT) {
return 1;
}
return -1;
}
if (ret < 0) {
uwsgi_error("uwsgi_simple_wait_write_hook()/poll()");
}
return ret;
}
/*
simplified write to client
(generally used as fallback)
*/
int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
wsgi_req->write_pos = 0;
for(;;) {
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
if (ret < 0) {
if (!uwsgi.ignore_write_errors) {
uwsgi_error("uwsgi_simple_write()");
}
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_write() TIMEOUT !!!\n");
wsgi_req->write_errors++;
return -1;
}
}
return 0;
}
+3 -3
View File
@@ -20,7 +20,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
char *xml_id;
char *xml_content;
size_t xml_size = 0;
int xml_size = 0;
if (uwsgi_check_scheme(filename)) {
colon = uwsgi_get_last_char(filename, '/');
@@ -47,7 +47,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
exit(1);
}
uwsgi_log_initial("[uWSGI] parsing config file %s\n", filename);
uwsgi_log("[uWSGI] parsing config file %s\n", filename);
element = xmlDocGetRootElement(doc);
if (element == NULL) {
@@ -221,7 +221,7 @@ void uwsgi_xml_config(char *filename, struct wsgi_request *wsgi_req, char *magic
char *colon;
char *xml_content;
size_t xml_size = 0;
int xml_size = 0;
int done = 0;
if (uwsgi_check_scheme(filename)) {
+4 -4
View File
@@ -61,9 +61,9 @@ int yaml_get_depth(char *line) {
return depth;
}
char *yaml_get_line(char *yaml, size_t size) {
char *yaml_get_line(char *yaml, off_t size) {
size_t i;
off_t i;
char *ptr = yaml;
int comment = 0;
@@ -96,7 +96,7 @@ char *yaml_get_line(char *yaml, size_t size) {
void uwsgi_yaml_config(char *file, char *magic_table[]) {
size_t len = 0;
int len = 0;
char *yaml;
int in_uwsgi_section = 0;
@@ -122,7 +122,7 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
}
}
uwsgi_log_initial("[uWSGI] getting YAML configuration from %s\n", file);
uwsgi_log("[uWSGI] getting YAML configuration from %s\n", file);
yaml = uwsgi_open_and_read(file, &len, 1, magic_table);
-115
View File
@@ -1,115 +0,0 @@
#include <uwsgi.h>
char gzheader[10] = { 0x1f, 0x8b, Z_DEFLATED, 0, 0, 0, 0, 0, 0, 3 };
char *uwsgi_gzip_chunk(z_stream *z, uint32_t *crc32, char *buf, size_t len, size_t *dlen) {
uwsgi_crc32(crc32, buf, len);
return uwsgi_deflate(z, buf, len, dlen);
}
struct uwsgi_buffer *uwsgi_gzip(char *buf, size_t len) {
z_stream z;
struct uwsgi_buffer *ub = NULL;
uint32_t gzip_crc32 = 0;
char *gzipped = NULL;
char *gzipped0 = NULL;
size_t dlen = 0;
size_t dlen0 = 0;
uwsgi_crc32(&gzip_crc32, NULL, 0);
if (uwsgi_deflate_init(&z, NULL, 0)) return NULL;
uwsgi_crc32(&gzip_crc32, buf, len);
gzipped = uwsgi_deflate(&z, buf, len, &dlen);
if (!gzipped) goto end;
gzipped0 = uwsgi_deflate(&z, NULL, 0, &dlen0);
if (!gzipped0) goto end;
ub = uwsgi_buffer_new(10 + dlen + dlen0 + 8);
if (uwsgi_buffer_append(ub, gzheader, 10)) goto end;
if (uwsgi_buffer_append(ub, gzipped, dlen)) goto end;
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
if (uwsgi_buffer_u32le(ub, gzip_crc32)) goto end;
if (uwsgi_buffer_u32le(ub, len)) goto end;
end:
if (gzipped) free(gzipped);
if (gzipped0) free(gzipped0);
deflateEnd(&z);
return ub;
}
int uwsgi_deflate_init(z_stream *z, char *dict, size_t dict_len) {
z->zalloc = Z_NULL;
z->zfree = Z_NULL;
z->opaque = Z_NULL;
if (deflateInit2(z, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY) != Z_OK) {
//if (deflateInit(z, Z_DEFAULT_COMPRESSION)) {
return -1;
}
if (dict && dict_len) {
if (deflateSetDictionary(z, (Bytef *) dict, dict_len) != Z_OK) {
return -1;
}
}
return 0;
}
int uwsgi_gzip_prepare(z_stream *z, char *dict, size_t dict_len, uint32_t *crc32) {
uwsgi_crc32(crc32, NULL, 0);
if (uwsgi_deflate_init(z, NULL, 0)) return -1;
return 0;
}
// fix and free a gzip stream
int uwsgi_gzip_fix(z_stream *z, uint32_t crc32, struct uwsgi_buffer *ub, size_t len) {
size_t dlen0 = 0;
char *gzipped0 = uwsgi_deflate(z, NULL, 0, &dlen0);
if (!gzipped0) goto end;
if (uwsgi_buffer_append(ub, gzipped0, dlen0)) goto end;
free(gzipped0);
if (uwsgi_buffer_u32le(ub, crc32)) goto end;
if (uwsgi_buffer_u32le(ub, len)) goto end;
deflateEnd(z);
return 0;
end:
if (gzipped0) free(gzipped0);
deflateEnd(z);
return -1;
}
char *uwsgi_deflate(z_stream *z, char *buf, size_t len, size_t *dlen) {
// calculate the amount of bytes needed for output (+30 should be enough)
Bytef *dbuf = uwsgi_malloc(len+30);
z->avail_in = len;
z->next_in = (Bytef *) buf;
z->avail_out = len+30;
z->next_out = dbuf;
if (len > 0) {
if (deflate(z, Z_SYNC_FLUSH) != Z_OK) {
free(dbuf);
return NULL;
}
}
else {
if (deflate(z, Z_FINISH) != Z_STREAM_END) {
free(dbuf);
return NULL;
}
deflateEnd(z);
}
*dlen = (z->next_out - dbuf);
return (char *) dbuf;
}
void uwsgi_crc32(uint32_t *ctx, char *buf, size_t len) {
if (!buf) {
*ctx = crc32(*ctx, Z_NULL, 0);
}
else {
*ctx = crc32(*ctx, (const Bytef *) buf, len);
}
}
View File
+90
View File
@@ -0,0 +1,90 @@
{% extends "admin/base_site.html" %}
{% load i18n %}
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="../">{% trans 'Home' %}</a> &rsaquo;
{% trans 'uWSGI' %}
</div>
{% endblock %}
{% block content %}
<div id="content-main">
<h1>uWSGI status</h1>
<b>masterpid:</b> {{masterpid}}<br/>
<b>started_on:</b> {{started_on}}<br/>
<b>buffer size:</b> {{buffer_size}}<br/>
<b>workers:</b> {{numproc}}<br/>
<b>total requests:</b> {{total_requests}}<br/>
<br/>
<div class="module" style="width:860px">
<table>
<caption style="width:860px">workers</caption>
<thead>
<tr>
<th scope="row">id</th>
<th scope="row">pid</th>
<th scope="row">requests</th>
<th scope="row">running time (milliseconds)</th>
<th scope="row">load</th>
<th scope="row">last spawn</th>
<th scope="row">respawn count</th>
<th scope="row">address space (vsz)</th>
<th scope="row">resident memory (rss)</th>
</tr>
</thead>
<tbody>
{% for w in workers %}
<tr>
<td align="center">{{w.id}}</td>
<td align="center">{{w.pid}}</td>
<td align="right">{{w.requests}}</td>
<td align="right">{{w.running_time}}</td>
<td align="right">{{w.load|floatformat:2}} %</td>
<td align="right">{{w.last_spawn_str}}</td>
<td align="right">{{w.respawn_count}}</td>
<td align="right">{{w.vsz|filesizeformat}}</td>
<td align="right">{{w.rss|filesizeformat}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="module" style="width:860px">
<table>
<caption style="width:860px">spooler jobs</caption>
<thead>
<tr>
<th scope="row">job filename</th>
<th scope="row">environment</th>
</tr>
</thead>
<tbody>
{% for j in jobs %}
<tr>
<td align="left">{{j.file}}</td>
<td align="left">{{j.env}}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% if masterpid %}
<br/>
<form {% if has_file_field %}enctype="multipart/form-data" {% endif %}action="reload/" method="post">
{% csrf_token %}
<input type="submit" value="gracefully reload uWSGI" name="_reload"/>
</form>
{% endif %}
</div>
{% endblock %}
+10
View File
@@ -0,0 +1,10 @@
import sys, os
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from django.conf.urls.defaults import *
urlpatterns = patterns('uwsgi_admin.views',
(r'^$', 'index'),
(r'^reload/$', 'reload')
)
+42
View File
@@ -0,0 +1,42 @@
import uwsgi
import time
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.contrib.admin.views.decorators import staff_member_required
from django.core.urlresolvers import reverse
from django.http import HttpResponseRedirect
def index(request):
workers = uwsgi.workers()
total_load = time.time() - uwsgi.started_on
for w in workers:
w['load'] = (100 * (w['running_time']/1000))/total_load
w['last_spawn_str'] = time.ctime(w['last_spawn'])
jobs = []
if 'spooler' in uwsgi.opt:
spooler_jobs = uwsgi.spooler_jobs()
for j in spooler_jobs:
jobs.append({'file': j, 'env': uwsgi.parsefile(j)})
return render_to_response('uwsgi.html', {'masterpid': uwsgi.masterpid(),
'started_on': time.ctime(uwsgi.started_on),
'buffer_size': uwsgi.buffer_size,
'total_requests': uwsgi.total_requests(),
'numproc': uwsgi.numproc,
'workers': workers,
'jobs': jobs,
}, RequestContext(request, {}))
index = staff_member_required(index)
def reload(request):
if uwsgi.masterpid() > 0:
uwsgi.reload()
request.user.message_set.create(message="uWSGI reloaded")
else:
request.user.message_set.create(message="The uWSGI master process is not active")
return HttpResponseRedirect(reverse(index))
reload = staff_member_required(reload)

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