Compare commits

...
103 Commits
Author SHA1 Message Date
unbit 3368a26ad3 Merge pull request #788 from dpetzold/mmap-check
Fix mmap error check in 1.4.
2014-12-06 07:03:32 +01:00
Derrick Petzold 5c2bb34708 ... 2014-12-05 16:00:11 -08:00
Derrick Petzold 9f084e151c Fix mmap error check.
Added logging of allocation error.
2014-12-05 15:27:45 -08:00
Unbit c0d61bc6a4 move uWSGI 1.4 to GPL2 + linking exception 2013-10-07 12:18:14 +02:00
Unbit ce8588ce4b backports for cheaper busyness from 1.9 2013-10-07 09:02:46 +02:00
Unbit 6c6cb1efc1 fixed reference counting bug in rpc and signal handlers 2013-08-29 14:43:52 +02:00
Unbit 6adbc37a31 removed old-style changelog 2013-08-23 14:57:06 +02:00
Unbit 688d3fff8c fixed python3 static files handling 2013-08-23 14:51:18 +02:00
Unbit c0b079deb0 backported python3 latin1 fix from 1.9 2013-07-02 16:22:20 +02:00
Unbit 9b30c8683b fixed backtrace-depth 2013-05-23 19:40:21 +02:00
Unbit 9113812b0d fixed python3 pyargv 2013-05-19 05:04:42 +02:00
Unbit 1abe9f2d12 fixed mule_msg 2013-05-18 18:27:11 +02:00
Unbit 9a37b3653f uWSGI 1.4.9 2013-03-09 10:01:34 +01:00
Unbit 65ad341a31 backported cache_update for lua and fixed its lock handling 2013-03-07 13:28:50 +01:00
Unbit bd31548903 re-try semop() on interrupt 2013-03-07 13:17:46 +01:00
Unbit dd536cf7ea removed jvm and jwsgi plugin as in 1.9 we have a really working implementation 2013-03-06 20:08:29 +01:00
Unbit efa27dfc6c better broodlord num computation 2013-03-06 19:56:55 +01:00
Unbit 91b14e0b34 improved broodlord mode 2013-03-06 19:13:32 +01:00
Unbit 74b3d25bcf call ERR_clear_error after each https session close 2013-03-06 10:36:05 +01:00
Unbit 3857e26e4c avoid crashing carbon on master shutdown 2013-03-03 13:43:55 +01:00
Unbit c7d3a27225 backported http-socket-modifier1/2 2013-03-02 16:25:17 +01:00
Unbit 4f50b4aafc completetd gemspec 2013-03-02 14:58:58 +01:00
Unbit d172fb4909 fixed gem generation 2013-03-02 14:49:03 +01:00
Unbit c842bb4917 allows building uwsgi as a gem 2013-03-02 14:37:14 +01:00
Unbit d6da6848be manage https re-handshake and fix gevent timeout management 2013-03-02 09:54:10 +01:00
Unbit b1caf56f49 various minor fixes in gateway initialization 2013-03-02 08:35:56 +01:00
Unbit 00c243bcce backported --for-glob 2013-03-01 15:23:38 +01:00
Unbit 575dd6beee backported add_timer and add_rb_timer for perl/psgi plugin 2013-03-01 15:20:40 +01:00
unbit 645d021d73 Merge pull request #166 from prymitive/carbon_hostname14
backported carbon hostname patch to 1.4.x
2013-03-01 06:18:52 -08:00
Łukasz Mierzwa 0ca320e5fd backported carbon hostname patch to 1.4.x 2013-03-01 15:15:46 +01:00
Unbit 7879a010e8 backported negative --log-alarm 2013-02-27 04:39:55 +01:00
Unbit 43dd1029ad fixed usage of ipcsem on linux 2013-02-27 04:26:59 +01:00
Unbit ce7d84b865 try to avoid the need to sync cache_first_available_item with cache_unused_stack 2013-02-27 01:43:03 +01:00
Unbit 7ab1795075 let's prepare for 1.4.7 2013-02-27 01:27:49 +01:00
Unbit e1ce4e1011 backporetd new carbon plugin and stats pusher subsystem 2013-02-27 01:26:24 +01:00
Unbit 0c02a5104a removed the old/broken/useless mono plugin, a new one will be in 1.9 2013-02-25 08:39:43 +01:00
Unbit 0e244fc59c added support for ruby 2 2013-02-25 07:34:34 +01:00
Unbit 5d6086c84a allows --attach-daemon without workers 2013-02-23 14:46:41 +01:00
Unbit a45be4f7a9 backported perl async fixes from 1.9 2013-02-23 13:35:41 +01:00
Unbit dd63bef92e backported --perl-arg and --perl-args 2013-02-23 13:28:51 +01:00
Unbit 621a05d879 another heroku python fix 2013-02-23 13:26:05 +01:00
Unbit b857690caf backported python plugin new build system (heroku friendly) 2013-02-23 12:07:45 +01:00
Unbit edb0a72dfd fixed a refcnt bug in psgi plugin 2013-02-23 08:26:08 +01:00
Unbit da4af442ad prepare for uWSGI 1.4.6 2013-02-20 16:03:27 +01:00
Unbit 04ff580075 improved muleloop in uwsgidecoraotors 2013-02-19 07:12:44 +01:00
Unbit 5925db13cf backported more logvars 2013-02-18 13:09:53 +01:00
Unbit d283fd1aae fixed master + emperor 2013-02-12 16:44:14 +01:00
Unbit 345b22d8f0 forget to reset SIGCHLD to SIG_DFL 2013-02-10 20:12:47 +01:00
Unbit b8fc89166d reset sigmask on startup 2013-02-10 19:52:50 +01:00
Unbit 50ffb9d258 reapply fixed-SERVER_PORT-in-routers-when-shared-sockets-are.patch 2013-02-09 17:34:31 +01:00
Unbit 9ae1b26d52 fixed suspend when harakiri is in place 2013-02-07 14:11:24 +01:00
Unbit f281d21a1b backported improved alarm_xmpp plugin 2013-01-31 09:59:54 +01:00
Unbit b9a2b92005 fixed PTHREAD_MUTEX_ROBUST [4] 2013-01-30 18:28:23 +01:00
Unbit 92a26d4ff6 fixed PTHREAD_MUTEX_ROBUST [3] 2013-01-30 18:26:24 +01:00
Unbit 51360416a7 fixed PTHREAD_MUTEX_ROBUST [2] 2013-01-30 18:20:22 +01:00
Unbit c7bc98a50c fixed PTHREAD_MUTEX_ROBUST 2013-01-30 18:16:24 +01:00
Unbit b4b5c0175a added __USE_UNIX98 to pthread.h 2013-01-30 18:14:37 +01:00
Unbit 7ed3eb36ee fixed PTHREAD_PRIO_INHERIT 2013-01-30 18:09:48 +01:00
Unbit 05c475f597 added --thunder-lock 2013-01-30 18:02:03 +01:00
Unbit c750dfc1e3 Revert "fixed SERVER_PORT in routers when shared sockets are in place"
This reverts commit 01b14f4395.
2013-01-30 16:57:59 +01:00
Unbit 01b14f4395 fixed SERVER_PORT in routers when shared sockets are in place 2013-01-30 16:32:19 +01:00
Unbit 46d7d4bf1d completed new logvars backport 2013-01-28 23:03:17 +01:00
Unbit 02d76f12e0 backported new logvars from 1.5 2013-01-28 22:44:54 +01:00
Unbit 719860a349 backported new rbtree implementation 2013-01-28 22:34:25 +01:00
Unbit 5cce0935fd backported master+emperor fix from 1.5 2013-01-28 16:37:13 +01:00
Unbit 24ef2a838f backported --touch-reload refactoring from 1.5 2013-01-28 16:23:57 +01:00
Unbit 8aa739b4b2 backported --emperor-procname 2013-01-26 04:20:00 +01:00
Unbit 9221e1953e fixed a cache collision bug 2013-01-23 20:22:28 +01:00
Roberto De Ioris 18592fb2bd fixed async mode when multiple fds are in place 2013-01-22 18:31:37 +01:00
Roberto De Ioris fc80eeb581 fixed bug in python uwsgi.workers() 2013-01-21 14:53:01 +01:00
Roberto De Ioris bc19b58681 prepare for uWSGI 1.4.5 2013-01-21 12:13:56 +01:00
Roberto De Ioris 8f2202eab5 reset cores/requests on worker startup 2013-01-21 12:13:32 +01:00
Roberto De Ioris aa2ecf14df correctly handle multithread exit 2013-01-21 12:09:25 +01:00
Roberto De Ioris 43f5792826 fixed test.psgi 2013-01-20 17:08:25 +01:00
unbit 36ff37e12c Update core/uwsgi.c 2013-01-18 09:21:16 +01:00
Roberto De Ioris 6dd6f961e8 removed a useless log 2013-01-16 19:34:41 +01:00
Roberto De Ioris 5dd5d92ffb fixed mule management 2013-01-16 17:10:22 +01:00
Roberto De Ioris 64f1b844bd fixed unix signal usage in mules and spooler 2013-01-16 16:50:10 +01:00
Roberto De Ioris e562c4691d fixed http-socket body storage leak 2013-01-16 16:27:47 +01:00
Roberto De Ioris 1cbab74f0e backported uwsgi::postfork and uwsgi::atexit 2013-01-16 14:52:13 +01:00
Roberto De Ioris 3053fdb25a backported --php-fallback 2013-01-14 16:44:30 +01:00
Roberto De Ioris f11f542242 improved mod_proxy_uwsgi 2013-01-13 12:37:22 +01:00
Roberto De Ioris 32ddf10cfa applied feature-extract-dump-the-specified-address-to-stdout.patch 2013-01-13 05:39:43 +01:00
Roberto De Ioris 1b54be396c applied Lua-bindings-for-lock-unlock-functions.patch 2013-01-13 05:38:01 +01:00
Roberto De Ioris f81a4f9736 fixed gevent leak 2013-01-12 17:18:53 +01:00
Roberto De Ioris 048b339593 allows building on debian etch 4 2013-01-10 22:26:24 +01:00
Roberto De Ioris 081a6b90bf added --python-version and --perl-version 2013-01-05 08:39:18 +01:00
Roberto De Ioris 97f1b6d649 fixed broodlord mode stats 2013-01-04 20:42:53 +01:00
Roberto De Ioris 593aba2b19 improved mod_proxy_uwsgi 2012-12-30 11:05:20 +01:00
Roberto De Ioris 47c9e5e3f0 fixed /proc check 2012-12-30 09:10:10 +01:00
Roberto De Ioris bca8bc0c4d fixed socket naming of fd 0 2012-12-30 09:07:38 +01:00
Roberto De Ioris a67dfdd542 fixed a https/corerouter corner-case bug 2012-12-21 11:32:33 +01:00
Roberto De Ioris d1bbe7e3f9 set HTTPS to on when behind stud 2012-12-21 09:01:10 +01:00
Roberto De Ioris 442c982aff backported --http-stud-prefix 2012-12-19 18:41:48 +01:00
Roberto De Ioris a2f50ccf2e report pos in failed uploads 2012-12-16 12:58:12 +01:00
Roberto De Ioris b1c5fef0dc fixed computation of post data 2012-12-16 12:18:13 +01:00
Roberto De Ioris f6d8ac52f4 applied more debug to https 2012-12-16 10:59:56 +01:00
Roberto De Ioris 94e4fcbfe1 added additional uwgsi-gevent error report 2012-12-15 20:36:26 +01:00
Roberto De Ioris c9e7b0f48e fixed wrong typecasting in yaml and fixed subscription system on 32 bit 2012-12-15 14:32:25 +01:00
Roberto De Ioris 2f932d8ca0 backported http internal router fixes 2012-12-13 15:34:47 +01:00
Roberto De Ioris c517320f7a prepare for next release (1.4.4) 2012-12-13 11:07:55 +01:00
Roberto De Ioris b0dae66264 applied 0001-allows-embedding-.cc-and-.m-files.patch 2012-12-13 11:07:37 +01:00
Roberto De Ioris 0d87ed7298 fix dup2() usage 2012-12-12 15:23:04 +01:00
67 changed files with 1884 additions and 1883 deletions
-679
View File
@@ -1,679 +0,0 @@
*** 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
+15
View File
@@ -1,3 +1,18 @@
----------------------------------------------------------------------
LINKING EXCEPTION
In addition to the permissions in the GNU General Public License,
the authors give you unlimited permission to link the compiled
version of this library into combinations with other programs,
and to distribute those combinations without any restriction
coming from the use of this file. (The General Public License
restrictions do apply in other respects; for example, they cover
modification of the file, and distribution when not linked into
a combined executable.)
----------------------------------------------------------------------
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
+30 -3
View File
@@ -1,3 +1,8 @@
/*
apxs2 -i -c mod_proxy_uwsgi.c
*/
#define APR_WANT_MEMFUNC
#define APR_WANT_STRFUNC
#include "apr_strings.h"
@@ -101,10 +106,26 @@ static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
ap_add_common_vars(r);
ap_add_cgi_vars(r);
// this is not a security problem (in Linux) as uWSGI destroy the env memory area readable in /proc
// and generally if you host untrusted apps in your server and allows them to read others uid /proc/<pid>
// files you have higher problems...
const char *auth = apr_table_get(r->headers_in, "Authorization");
if (auth) {
apr_table_setn(r->subprocess_env, "HTTP_AUTHORIZATION", auth);
}
const char *script_name = apr_table_get(r->subprocess_env, "SCRIPT_NAME");
const char *path_info = apr_table_get(r->subprocess_env, "PATH_INFO");
if (script_name && path_info) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", apr_pstrndup(r->pool, script_name, strlen(script_name)-strlen(path_info)));
if (strcmp(path_info, "/")) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", apr_pstrndup(r->pool, script_name, strlen(script_name)-strlen(path_info)));
}
else {
if (!strcmp(script_name, "/")) {
apr_table_set(r->subprocess_env, "SCRIPT_NAME", "");
}
}
}
env_table = apr_table_elts(r->subprocess_env);
@@ -135,7 +156,7 @@ static int uwsgi_send_headers(request_rec *r, proxy_conn_rec *conn)
buf[0] = 0;
buf[1] = (uint8_t) (pktsize & 0xff);
buf[2] = (uint8_t) ((pktsize >> 8) & 0xff);
buf[0] = 0;
buf[3] = 0;
return uwsgi_send(conn, buf, headerlen, r);
}
@@ -326,7 +347,13 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
}
// ADD PATH_INFO
apr_table_add(r->subprocess_env, "PATH_INFO", url+strlen(worker->name));
size_t w_len = strlen(worker->name);
char *u_path_info = r->filename + 6 + w_len;
int delta = 0;
if (u_path_info[0] != '/') {
delta = 1;
}
apr_table_add(r->subprocess_env, "PATH_INFO", url+w_len-delta);
/* Create space for state information */
+4
View File
@@ -0,0 +1,4 @@
#!/usr/bin/env ruby
cmd = File.expand_path "#{File.dirname(__FILE__)}/../ext/uwsgi/uwsgi.ruby"
exec(cmd, *ARGV)
+9 -3
View File
@@ -136,7 +136,7 @@ static struct uwsgi_alarm_instance *uwsgi_alarm_get_instance(char *name) {
}
static int uwsgi_alarm_log_add(char *alarms, char *regexp) {
static int uwsgi_alarm_log_add(char *alarms, char *regexp, int negate) {
struct uwsgi_alarm_log *old_ual = NULL, *ual = uwsgi.alarm_logs;
while (ual) {
@@ -148,6 +148,7 @@ static int uwsgi_alarm_log_add(char *alarms, char *regexp) {
if (uwsgi_regexp_build(regexp, &ual->pattern, &ual->pattern_extra)) {
return -1;
}
ual->negate = negate;
if (old_ual) {
old_ual->next = ual;
@@ -223,7 +224,7 @@ void uwsgi_alarms_init() {
*space = 0;
char *regexp = space + 1;
// here the log-alarm is created
if (uwsgi_alarm_log_add(line, regexp)) {
if (uwsgi_alarm_log_add(line, regexp, usl->custom)) {
uwsgi_log("invalid log-alarm: %s\n", usl->value);
exit(1);
}
@@ -239,7 +240,12 @@ void uwsgi_alarm_log_check(char *msg, size_t len) {
struct uwsgi_alarm_log *ual = uwsgi.alarm_logs;
while (ual) {
if (uwsgi_regexp_match(ual->pattern, ual->pattern_extra, msg, len) >= 0) {
uwsgi_alarm_log_run(ual, msg, len);
if (!ual->negate) {
uwsgi_alarm_log_run(ual, msg, len);
}
else {
break;
}
}
ual = ual->next;
}
+11 -9
View File
@@ -99,23 +99,23 @@ struct wsgi_request *find_first_available_wsgi_req() {
void async_expire_timeouts() {
struct wsgi_request *wsgi_req;
time_t current_time = uwsgi_now();
uint64_t current_time = (uint64_t) uwsgi_now();
struct uwsgi_async_fd *uaf = NULL, *current_uaf;
struct uwsgi_rb_timer *urbt;
for (;;) {
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
urbt = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
if (urbt == NULL)
return;
if (urbt->key <= current_time) {
if (urbt->value <= current_time) {
wsgi_req = (struct wsgi_request *) urbt->data;
// timeout expired
wsgi_req->async_timed_out = 1;
rb_erase(&wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
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;
@@ -258,12 +258,12 @@ void async_loop() {
timeout = 0;
}
else {
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts);
min_timeout = uwsgi_min_rb_timer(uwsgi.rb_async_timeouts, NULL);
if (uwsgi.async_runqueue_cnt) {
timeout = 0;
}
if (min_timeout) {
timeout = min_timeout->key - uwsgi_now();
timeout = min_timeout->value - uwsgi_now();
if (timeout <= 0) {
async_expire_timeouts();
timeout = 0;
@@ -354,13 +354,14 @@ void async_loop() {
if (uwsgi.wsgi_req) {
proto_parser_status = uwsgi.wsgi_req->socket->proto(uwsgi.wsgi_req);
// reset timeout
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
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
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
continue;
@@ -395,7 +396,7 @@ void async_loop() {
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
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;
}
@@ -405,6 +406,7 @@ void async_loop() {
// put the request in the runqueue again
runqueue_push(uwsgi.wsgi_req);
break;
}
}
@@ -432,7 +434,7 @@ void async_loop() {
}
uwsgi.wsgi_req->waiting_fds = NULL;
if (uwsgi.wsgi_req->async_timeout) {
rb_erase(&uwsgi.wsgi_req->async_timeout->rbt, uwsgi.rb_async_timeouts);
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;
}
+10
View File
@@ -114,3 +114,13 @@ int uwsgi_buffer_send(struct uwsgi_buffer *ub, int fd) {
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);
}
+17 -13
View File
@@ -58,20 +58,28 @@ void uwsgi_init_cache() {
exit(1);
}
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, uwsgi.cache_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, cache_fd, 0);
if (uwsgi.cache_items == MAP_FAILED) {
uwsgi_log("Unable to mmap %llu bytes.\n", uwsgi.cache_filesize);
uwsgi_error("mmap()");
exit(1);
}
uwsgi_cache_fix();
}
else {
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
ssize_t cache_size = (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items);
uwsgi.cache_items = (struct uwsgi_cache_item *) mmap(NULL, cache_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (uwsgi.cache_items == MAP_FAILED) {
uwsgi_log("Unable to mmap %llu bytes.\n", cache_size);
uwsgi_error("mmap()");
exit(1);
}
int i;
for (i = 0; i < (int) uwsgi.cache_max_items; i++) {
memset(&uwsgi.cache_items[i], 0, sizeof(struct uwsgi_cache_item));
}
}
if (!uwsgi.cache_items) {
uwsgi_error("mmap()");
exit(1);
}
/*
uwsgi.cache = mmap(NULL, uwsgi.cache_blocksize * uwsgi.cache_max_items, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
@@ -105,7 +113,7 @@ static inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uint32_t hash = djb33x_hash(key, keylen);
int hash_key = hash % 0xffff;
uint32_t hash_key = hash % 0xffff;
uint64_t slot = uwsgi.cache_hashtable[hash_key];
@@ -117,8 +125,9 @@ static inline uint64_t uwsgi_cache_get_index(char *key, uint16_t keylen) {
uci = &uwsgi.cache_items[slot];
// first round
if (hash_key != uci->djbhash % 0xffff) return 0;
if (uci->djbhash != hash)
return 0;
goto cycle;
if (uci->keysize != keylen)
goto cycle;
if (memcmp(uci->key, key, keylen))
@@ -144,7 +153,7 @@ cycle:
}
}
if (uci->djbhash != hash)
return 0;
continue;
if (uci->keysize != keylen)
continue;
if (!memcmp(uci->key, key, keylen))
@@ -188,11 +197,6 @@ int uwsgi_cache_del(char *key, uint16_t keylen, uint64_t index) {
uci->valsize = 0;
uwsgi.shared->cache_unused_stack_ptr++;
uwsgi.cache_unused_stack[uwsgi.shared->cache_unused_stack_ptr] = index;
// try to return to initial condition...
if (index == uwsgi.shared->cache_first_available_item - 1) {
uwsgi.shared->cache_first_available_item--;
//uwsgi_log("FACI: %llu STACK PTR: %llu\n", (unsigned long long) uwsgi.shared->cache_first_available_item, (unsigned long long) uwsgi.shared->cache_unused_stack_ptr);
}
ret = 0;
// relink collisioned entry
if (uci->prev) {
+1 -1
View File
@@ -215,7 +215,7 @@ void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {
exit(1);
}
if (devnull != 0) {
if (dup2(devnull, 0)) {
if (dup2(devnull, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
+62 -9
View File
@@ -6,7 +6,6 @@ a supervisor for multiple uWSGI instances
*/
#include "uwsgi.h"
#include <glob.h>
extern struct uwsgi_server uwsgi;
@@ -186,8 +185,24 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
while (c_ui) {
if (c_ui->scanner == ues) {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
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);
}
}
}
c_ui = c_ui->ui_next;
@@ -246,9 +261,25 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
while (c_ui) {
if (c_ui->scanner == ues) {
if (stat(c_ui->name, &st)) {
emperor_stop(c_ui);
}
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);
}
}
}
c_ui = c_ui->ui_next;
}
@@ -549,6 +580,10 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
}
if (n_ui->zerg) {
uwsgi.emperor_broodlord_num++;
}
// TODO pre-start hook
// a new uWSGI instance will start
@@ -602,6 +637,16 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
}
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)) {
@@ -709,7 +754,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
exit(1);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0)) {
if (dup2(stdin_fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
@@ -1023,7 +1068,7 @@ 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");
emperor_add(NULL, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
free(zerg_name);
}
}
@@ -1324,13 +1369,21 @@ end:
void uwsgi_emperor_start() {
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.master_process) {
if (uwsgi.emperor_procname) {
uwsgi_set_processname(uwsgi.emperor_procname);
}
uwsgi_notify_ready();
emperor_loop();
// never here
exit(1);
}
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
if (uwsgi.emperor_procname) {
uwsgi.emperor_pid = uwsgi_fork(uwsgi.emperor_procname);
}
else {
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
}
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
+6 -1
View File
@@ -41,6 +41,10 @@ struct uwsgi_gateway *register_gateway(char *name, void (*loop) (int, void *), v
return ug;
}
static void gateway_brutal_end() {
_exit(UWSGI_END_CODE);
}
void gateway_respawn(int id) {
pid_t gw_pid;
@@ -65,6 +69,7 @@ void gateway_respawn(int id) {
}
#endif
uwsgi.mypid = getpid();
atexit(gateway_brutal_end);
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
@@ -77,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;
+32 -2
View File
@@ -45,6 +45,10 @@ static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
#ifdef UWSGI_LOCK_USE_MUTEX
#ifdef OBSOLETE_LINUX_KERNEL
#undef EOWNERDEAD
#endif
#ifdef EOWNERDEAD
#define UWSGI_LOCK_ENGINE_NAME "pthread robust mutexes"
int uwsgi_pthread_robust_mutexes_enabled = 1;
@@ -60,6 +64,12 @@ int uwsgi_pthread_robust_mutexes_enabled = 1;
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlock_t)
#endif
#ifndef PTHREAD_PRIO_INHERIT
int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr,
int __protocol);
#define PTHREAD_PRIO_INHERIT 1
#endif
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
@@ -81,8 +91,16 @@ retry:
}
#ifdef EOWNERDEAD
#ifndef PTHREAD_MUTEX_ROBUST
#define PTHREAD_MUTEX_ROBUST PTHREAD_MUTEX_ROBUST_NP
#endif
if (pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT)) {
uwsgi_log("unable to set PTHREAD_PRIO_INHERIT\n");
exit(1);
}
if (uwsgi_pthread_robust_mutexes_enabled) {
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST_NP)) {
if (pthread_mutexattr_setrobust_np(&attr, PTHREAD_MUTEX_ROBUST)) {
uwsgi_log("unable to make the mutex 'robust'\n");
exit(1);
}
@@ -460,7 +478,9 @@ 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()");
}
}
@@ -475,7 +495,9 @@ 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()");
}
@@ -556,8 +578,10 @@ void uwsgi_setup_locking() {
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
uwsgi.lock_size = 8;
uwsgi.rwlock_size = 8;
return;
goto ready;
}
uwsgi_log("unable to find lock engine \"%s\"\n", uwsgi.lock_engine);
exit(1);
}
uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
@@ -578,6 +602,7 @@ void uwsgi_setup_locking() {
// application generic lock
int i;
ready:
uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
for (i = 0; i < uwsgi.locks + 1; i++) {
uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
@@ -608,6 +633,11 @@ void uwsgi_setup_locking() {
uwsgi.cron_table_lock = uwsgi_lock_init("cron");
}
if (uwsgi.use_thunder_lock) {
// process shared thunder lock
uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");
}
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
}
+209 -7
View File
@@ -815,6 +815,7 @@ struct uwsgi_logger *uwsgi_get_logger_from_id(char *id) {
void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
struct uwsgi_logchunk *logchunk = uwsgi.logchunks;
ssize_t rlen = 0;
const char *empty_var = "-";
while (logchunk) {
int pos = logchunk->vec;
// raw string
@@ -851,6 +852,11 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
uwsgi.logvectors[wsgi_req->async_id][pos].iov_len = 0;
}
}
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;
}
logchunk = logchunk->next;
}
@@ -862,7 +868,9 @@ void uwsgi_logit_lf(struct wsgi_request *wsgi_req) {
while (logchunk) {
if (logchunk->free) {
if (uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_len > 0) {
free(uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_base);
if (uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_base != empty_var) {
free(uwsgi.logvectors[wsgi_req->async_id][logchunk->vec].iov_base);
}
}
}
logchunk = logchunk->next;
@@ -923,17 +931,38 @@ void uwsgi_build_log_format(char *format) {
}
ssize_t uwsgi_lf_status(struct wsgi_request *wsgi_req, char **buf) {
static ssize_t uwsgi_lf_status(struct wsgi_request *wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->status);
return strlen(*buf);
}
ssize_t uwsgi_lf_epoch(struct wsgi_request * wsgi_req, char **buf) {
static ssize_t uwsgi_lf_rsize(struct wsgi_request *wsgi_req, char **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);
}
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);
}
static ssize_t uwsgi_lf_cl(struct wsgi_request *wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->post_cl);
return strlen(*buf);
}
static ssize_t uwsgi_lf_epoch(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(uwsgi_now());
return strlen(*buf);
}
ssize_t uwsgi_lf_ctime(struct wsgi_request * wsgi_req, char **buf) {
static ssize_t uwsgi_lf_ctime(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_malloc(26);
#ifdef __sun__
ctime_r((const time_t *) &wsgi_req->start_of_request_in_sec, *buf, 26);
@@ -943,23 +972,98 @@ ssize_t uwsgi_lf_ctime(struct wsgi_request * wsgi_req, char **buf) {
return 24;
}
ssize_t uwsgi_lf_time(struct wsgi_request * wsgi_req, char **buf) {
static ssize_t uwsgi_lf_time(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->start_of_request / 1000000);
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;
}
ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
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);
}
ssize_t uwsgi_lf_msecs(struct wsgi_request * wsgi_req, char **buf) {
static ssize_t uwsgi_lf_msecs(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str((wsgi_req->end_of_request - wsgi_req->start_of_request) / 1000);
return strlen(*buf);
}
static ssize_t uwsgi_lf_pid(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(uwsgi.mypid);
return strlen(*buf);
}
static ssize_t uwsgi_lf_wid(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(uwsgi.mywid);
return strlen(*buf);
}
static ssize_t uwsgi_lf_switches(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->switches);
return strlen(*buf);
}
static ssize_t uwsgi_lf_vars(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->var_cnt);
return strlen(*buf);
}
static ssize_t uwsgi_lf_core(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->async_id);
return strlen(*buf);
}
static ssize_t uwsgi_lf_vsz(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(uwsgi.workers[uwsgi.mywid].vsz_size);
return strlen(*buf);
}
static ssize_t uwsgi_lf_rss(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(uwsgi.workers[uwsgi.mywid].rss_size);
return strlen(*buf);
}
static ssize_t uwsgi_lf_vszM(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
return strlen(*buf);
}
static ssize_t uwsgi_lf_rssM(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
return strlen(*buf);
}
static ssize_t uwsgi_lf_pktsize(struct wsgi_request * wsgi_req, char **buf) {
*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);
return strlen(*buf);
}
static ssize_t uwsgi_lf_modifier2(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->uh.modifier2);
return strlen(*buf);
}
static ssize_t uwsgi_lf_headers(struct wsgi_request * wsgi_req, char **buf) {
*buf = uwsgi_num2str(wsgi_req->header_cnt);
return strlen(*buf);
}
void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
@@ -1018,11 +1122,39 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->pos = offsetof(struct wsgi_request, protocol);
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);
}
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;
}
else if (!uwsgi_strncmp(ptr, len, "micros", 6)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_micros;
@@ -1038,6 +1170,11 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->func = uwsgi_lf_time;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "ltime", 5)) {
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;
@@ -1048,6 +1185,71 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
logchunk->func = uwsgi_lf_epoch;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "pid", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_pid;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "wid", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_wid;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "switches", 8)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_switches;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "vars", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_vars;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "core", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_core;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "vsz", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_vsz;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "rss", 3)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_rss;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "vszM", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_vszM;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "rssM", 4)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_rssM;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "pktsize", 7)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_pktsize;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "modifier1", 9)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_modifier1;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "modifier2", 9)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_modifier2;
logchunk->free = 1;
}
else if (!uwsgi_strncmp(ptr, len, "headers", 7)) {
logchunk->type = 3;
logchunk->func = uwsgi_lf_headers;
logchunk->free = 1;
}
// logvar
else {
logchunk->type = 2;
+17 -11
View File
@@ -231,28 +231,28 @@ int uwsgi_master_check_mercy() {
}
void expire_rb_timeouts(struct rb_root *root) {
void expire_rb_timeouts(struct uwsgi_rbtree *tree) {
time_t current = uwsgi_now();
uint64_t current = (uint64_t) uwsgi_now();
struct uwsgi_rb_timer *urbt;
struct uwsgi_signal_rb_timer *usrbt;
for (;;) {
urbt = uwsgi_min_rb_timer(root);
urbt = uwsgi_min_rb_timer(tree, NULL);
if (urbt == NULL)
return;
if (urbt->key <= current) {
if (urbt->value <= current) {
// remove the timeout and add another
usrbt = (struct uwsgi_signal_rb_timer *) urbt->data;
rb_erase(&usrbt->uwsgi_rb_timer->rbt, root);
free(usrbt->uwsgi_rb_timer);
uwsgi_del_rb_timer(tree, urbt);
free(urbt);
usrbt->iterations_done++;
uwsgi_route_signal(usrbt->sig);
if (!usrbt->iterations || usrbt->iterations_done < usrbt->iterations) {
usrbt->uwsgi_rb_timer = uwsgi_add_rb_timer(root, uwsgi_now() + usrbt->value, usrbt);
usrbt->uwsgi_rb_timer = uwsgi_add_rb_timer(tree, uwsgi_now() + usrbt->value, usrbt);
}
continue;
}
@@ -622,7 +622,7 @@ int master_loop(char **argv, char **environ) {
int check_interval = 1;
struct uwsgi_rb_timer *min_timeout;
struct rb_root *rb_timers = uwsgi_init_rb_timer();
struct uwsgi_rbtree *rb_timers = uwsgi_init_rb_timer();
if (uwsgi.procname_master) {
@@ -738,7 +738,7 @@ int master_loop(char **argv, char **environ) {
}
if (uwsgi.requested_stats_pushers) {
if (uwsgi.stats_pusher_instances) {
if (!uwsgi_thread_new(uwsgi_stats_pusher_loop)) {
uwsgi_log("!!! unable to spawn stats pusher thread !!!\n");
exit(1);
@@ -975,12 +975,12 @@ int master_loop(char **argv, char **environ) {
int interesting_fd = -1;
if (ushared->rb_timers_cnt > 0) {
min_timeout = uwsgi_min_rb_timer(rb_timers);
min_timeout = uwsgi_min_rb_timer(rb_timers, NULL);
if (min_timeout == NULL) {
check_interval = uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL];
}
else {
check_interval = min_timeout->key - uwsgi_now();
check_interval = min_timeout->value - uwsgi_now();
if (check_interval <= 0) {
expire_rb_timeouts(rb_timers);
check_interval = 0;
@@ -1461,6 +1461,12 @@ health_cycle:
continue;
#endif
if (uwsgi.emperor_pid >= 0 && diedpid == uwsgi.emperor_pid) {
uwsgi_log_verbose("!!! Emperor died !!!\n");
uwsgi_emperor_start();
continue;
}
pid_found = 0;
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].pid == diedpid) {
+7 -1
View File
@@ -508,7 +508,8 @@ int uwsgi_respawn_worker(int wid) {
uwsgi.workers[wid].cheaped = 0;
uwsgi.workers[wid].busy = 0;
uwsgi.workers[wid].suspended = 0;
// SUSPENSION is managed by the user, not the master...
//uwsgi.workers[wid].suspended = 0;
uwsgi.workers[wid].sig = 0;
// this is required for various checks
@@ -555,6 +556,11 @@ int uwsgi_respawn_worker(int wid) {
// reset the apps count with a copy from the master
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
// reset wsgi_request structures
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];
+15 -4
View File
@@ -41,6 +41,17 @@ void uwsgi_mule(int id) {
uwsgi_error("prctl()");
}
#endif
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.muleid = id;
// avoid race conditions
uwsgi.mules[id - 1].id = id;
@@ -71,7 +82,7 @@ void uwsgi_mule(int id) {
if (uwsgi.p[i]->mule) {
if (uwsgi.p[i]->mule(uwsgi.mules[id - 1].patch) == 1) {
// never here
break;
end_me(1);
}
}
}
@@ -394,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_signal_pipe(uwsgi.shared->mule_queue_pipe);
create_msg_pipe(uwsgi.shared->mule_queue_pipe, uwsgi.mule_msg_size);
for (i = 0; i < uwsgi.mules_cnt; i++) {
// create the socket pipe
create_signal_pipe(uwsgi.mules[i].signal_pipe);
create_signal_pipe(uwsgi.mules[i].queue_pipe);
create_msg_pipe(uwsgi.mules[i].queue_pipe, uwsgi.mule_msg_size);
uwsgi.mules[i].id = i + 1;
@@ -428,7 +439,7 @@ void uwsgi_setup_mules_and_farms() {
// create the socket pipe
create_signal_pipe(uwsgi.farms[i].signal_pipe);
create_signal_pipe(uwsgi.farms[i].queue_pipe);
create_msg_pipe(uwsgi.farms[i].queue_pipe, uwsgi.mule_msg_size);
char *p = strtok(mules_list, ",");
while (p != NULL) {
+1 -1
View File
@@ -331,7 +331,7 @@ static int uwsgi_offload_net_transfer(struct uwsgi_thread *ut, struct uwsgi_offl
}
}
else if (fd == uor->s) {
rlen = read(uor->fd, uor->buf, 4096);
rlen = read(uor->s, uor->buf, 4096);
if (rlen > 0) {
uor->to_write = rlen;
uor->pos = 0;
+8
View File
@@ -883,6 +883,14 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->authorization = ptrbuf;
wsgi_req->authorization_len = strsize;
}
else if (!uwsgi_strncmp("HTTP_USER_AGENT", 15, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->user_agent = ptrbuf;
wsgi_req->user_agent_len = strsize;
}
else if (!uwsgi_strncmp("HTTP_REFERER", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->referer = ptrbuf;
wsgi_req->referer_len = strsize;
}
else if (!uwsgi_strncmp("DOCUMENT_ROOT", 13, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->document_root = ptrbuf;
wsgi_req->document_root_len = strsize;
+334 -32
View File
@@ -1,65 +1,367 @@
/*
uWSGI timers implementation
uWSGI rbtree implementation based on nginx
based on Linux hrtimers and nginx timeout management.
rbtree with allowed duplicate keys is used
Copyright (C) Igor Sysoev
Copyright (C) Nginx, Inc.
Copyright (C) Unbit S.a.s.
The red-black tree code is based on the algorithm described in
the "Introduction to Algorithms" by Cormen, Leiserson and Rivest.
*/
#include "uwsgi.h"
#include <uwsgi.h>
struct rb_root *uwsgi_init_rb_timer() {
#define uwsgi_rbt_red(node) ((node)->color = 1)
#define uwsgi_rbt_black(node) ((node)->color = 0)
#define uwsgi_rbt_is_red(node) ((node)->color)
#define uwsgi_rbt_is_black(node) (!uwsgi_rbt_is_red(node))
#define uwsgi_rbt_copy_color(n1, n2) (n1->color = n2->color)
struct rb_root *u_rb_root = uwsgi_malloc(sizeof(struct rb_root));
u_rb_root->rb_node = NULL;
struct uwsgi_rbtree *uwsgi_init_rb_timer() {
return u_rb_root;
struct uwsgi_rbtree *tree = uwsgi_calloc(sizeof(struct uwsgi_rbtree));
struct uwsgi_rb_timer *sentinel = uwsgi_calloc(sizeof(struct uwsgi_rb_timer));
// no need to set it black, calloc already did it
//uwsgi_rbt_black(sentinel);
tree->root = sentinel;
tree->sentinel = sentinel;
return tree;
}
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct rb_root *root) {
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct uwsgi_rbtree *tree, struct uwsgi_rb_timer *node) {
struct rb_node *node = root->rb_node;
if (!node)
node = tree->root;
struct uwsgi_rb_timer *sentinel = tree->sentinel;
if (node == NULL)
return NULL;
if (tree->root == sentinel) return NULL;
while (node->rb_left != NULL) {
node = node->rb_left;
while (node->left != sentinel) {
node = node->left;
}
return ((struct uwsgi_rb_timer *) node);
return node;
}
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct rb_root *root, time_t key, void *data) {
static void uwsgi_rbtree_lr(struct uwsgi_rb_timer **root, struct uwsgi_rb_timer *sentinel, struct uwsgi_rb_timer *node) {
struct uwsgi_rb_timer *urbt = uwsgi_malloc(sizeof(struct uwsgi_rb_timer));
struct rb_node **p = &root->rb_node, *parent = NULL;
struct uwsgi_rb_timer *current_rb_timer;
struct uwsgi_rb_timer *temp;
memset(urbt, 0, sizeof(struct uwsgi_rb_timer));
temp = node->right;
node->right = temp->left;
urbt->key = key;
urbt->data = data;
if (temp->left != sentinel) {
temp->left->parent = node;
}
while (*p) {
parent = *p;
temp->parent = node->parent;
current_rb_timer = (struct uwsgi_rb_timer *) parent;
if (node == *root) {
*root = temp;
}
else if (node == node->parent->left) {
node->parent->left = temp;
}
else {
node->parent->right = temp;
}
temp->left = node;
node->parent = temp;
}
static void uwsgi_rbtree_rr(struct uwsgi_rb_timer **root, struct uwsgi_rb_timer *sentinel, struct uwsgi_rb_timer *node) {
struct uwsgi_rb_timer *temp;
temp = node->left;
node->left = temp->right;
if (temp->right != sentinel) {
temp->right->parent = node;
}
temp->parent = node->parent;
if (node == *root) {
*root = temp;
}
else if (node == node->parent->right) {
node->parent->right = temp;
}
else {
node->parent->left = temp;
}
temp->right = node;
node->parent = temp;
}
static void uwsgi_rbt_add(struct uwsgi_rb_timer *temp, struct uwsgi_rb_timer *node, struct uwsgi_rb_timer *sentinel) {
struct uwsgi_rb_timer **p;
for (;;) {
p = (node->value < temp->value) ? &temp->left : &temp->right;
if (*p == sentinel)
break;
temp = *p;
}
*p = node;
node->parent = temp;
node->left = sentinel;
node->right = sentinel;
uwsgi_rbt_red(node);
}
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct uwsgi_rbtree *tree, uint64_t value, void *data) {
struct uwsgi_rb_timer *node = uwsgi_malloc(sizeof(struct uwsgi_rb_timer));
struct uwsgi_rb_timer *new_node = node;
node->value = value;
node->data = data;
struct uwsgi_rb_timer *temp = NULL;
/* a binary tree insert */
struct uwsgi_rb_timer **root = &tree->root;
struct uwsgi_rb_timer *sentinel = tree->sentinel;
if (*root == sentinel) {
node->parent = NULL;
node->left = sentinel;
node->right = sentinel;
uwsgi_rbt_black(node);
*root = node;
return new_node;
}
uwsgi_rbt_add(*root, node, sentinel);
/* re-balance tree */
while (node != *root && uwsgi_rbt_is_red(node->parent)) {
if (node->parent == node->parent->parent->left) {
temp = node->parent->parent->right;
if (uwsgi_rbt_is_red(temp)) {
uwsgi_rbt_black(node->parent);
uwsgi_rbt_black(temp);
uwsgi_rbt_red(node->parent->parent);
node = node->parent->parent;
}
else {
if (node == node->parent->right) {
node = node->parent;
uwsgi_rbtree_lr(root, sentinel, node);
}
uwsgi_rbt_black(node->parent);
uwsgi_rbt_red(node->parent->parent);
uwsgi_rbtree_rr(root, sentinel, node->parent->parent);
}
if (key <= current_rb_timer->key) {
p = &(*p)->rb_left;
}
else {
p = &(*p)->rb_right;
temp = node->parent->parent->left;
if (uwsgi_rbt_is_red(temp)) {
uwsgi_rbt_black(node->parent);
uwsgi_rbt_black(temp);
uwsgi_rbt_red(node->parent->parent);
node = node->parent->parent;
}
else {
if (node == node->parent->left) {
node = node->parent;
uwsgi_rbtree_rr(root, sentinel, node);
}
uwsgi_rbt_black(node->parent);
uwsgi_rbt_red(node->parent->parent);
uwsgi_rbtree_lr(root, sentinel, node->parent->parent);
}
}
}
rb_link_node((struct rb_node *) urbt, parent, p);
uwsgi_rbt_black(*root);
rb_insert_color((struct rb_node *) urbt, root);
return new_node;
}
return urbt;
void uwsgi_del_rb_timer(struct uwsgi_rbtree *tree, struct uwsgi_rb_timer *node) {
uint8_t red;
struct uwsgi_rb_timer **root, *sentinel, *subst, *temp, *w;
/* a binary tree delete */
root = &tree->root;
sentinel = tree->sentinel;
if (node->left == sentinel) {
temp = node->right;
subst = node;
}
else if (node->right == sentinel) {
temp = node->left;
subst = node;
}
else {
subst = uwsgi_min_rb_timer(tree, node->right);
if (subst->left != sentinel) {
temp = subst->left;
}
else {
temp = subst->right;
}
}
if (subst == *root) {
*root = temp;
uwsgi_rbt_black(temp);
return;
}
red = uwsgi_rbt_is_red(subst);
if (subst == subst->parent->left) {
subst->parent->left = temp;
}
else {
subst->parent->right = temp;
}
if (subst == node) {
temp->parent = subst->parent;
}
else {
if (subst->parent == node) {
temp->parent = subst;
}
else {
temp->parent = subst->parent;
}
subst->left = node->left;
subst->right = node->right;
subst->parent = node->parent;
uwsgi_rbt_copy_color(subst, node);
if (node == *root) {
*root = subst;
}
else {
if (node == node->parent->left) {
node->parent->left = subst;
}
else {
node->parent->right = subst;
}
}
if (subst->left != sentinel) {
subst->left->parent = subst;
}
if (subst->right != sentinel) {
subst->right->parent = subst;
}
}
if (red) {
return;
}
/* a delete fixup */
while (temp != *root && uwsgi_rbt_is_black(temp)) {
if (temp == temp->parent->left) {
w = temp->parent->right;
if (uwsgi_rbt_is_red(w)) {
uwsgi_rbt_black(w);
uwsgi_rbt_red(temp->parent);
uwsgi_rbtree_lr(root, sentinel, temp->parent);
w = temp->parent->right;
}
if (uwsgi_rbt_is_black(w->left) && uwsgi_rbt_is_black(w->right)) {
uwsgi_rbt_red(w);
temp = temp->parent;
}
else {
if (uwsgi_rbt_is_black(w->right)) {
uwsgi_rbt_black(w->left);
uwsgi_rbt_red(w);
uwsgi_rbtree_rr(root, sentinel, w);
w = temp->parent->right;
}
uwsgi_rbt_copy_color(w, temp->parent);
uwsgi_rbt_black(temp->parent);
uwsgi_rbt_black(w->right);
uwsgi_rbtree_lr(root, sentinel, temp->parent);
temp = *root;
}
}
else {
w = temp->parent->left;
if (uwsgi_rbt_is_red(w)) {
uwsgi_rbt_black(w);
uwsgi_rbt_red(temp->parent);
uwsgi_rbtree_rr(root, sentinel, temp->parent);
w = temp->parent->left;
}
if (uwsgi_rbt_is_black(w->left) && uwsgi_rbt_is_black(w->right)) {
uwsgi_rbt_red(w);
temp = temp->parent;
}
else {
if (uwsgi_rbt_is_black(w->left)) {
uwsgi_rbt_black(w->right);
uwsgi_rbt_red(w);
uwsgi_rbtree_lr(root, sentinel, w);
w = temp->parent->left;
}
uwsgi_rbt_copy_color(w, temp->parent);
uwsgi_rbt_black(temp->parent);
uwsgi_rbt_black(w->left);
uwsgi_rbtree_rr(root, sentinel, temp->parent);
temp = *root;
}
}
}
uwsgi_rbt_black(temp);
}
+39 -30
View File
@@ -62,40 +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;
char *res = uwsgi_malloc(dst_n + (src_n * n) + 1);
char *ptr = res;
size_t dollars = n;
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++ = dst[i];
}
dollar = 0;
}
else {
if (dst[i] == '$') {
dollar = 1;
}
else {
*ptr++ = dst[i];
}
}
}
for(i=0;i<dst_n;i++) {
if (dst[i] == '$') {
dollars++;
}
}
*ptr++ = 0;
char *res = uwsgi_malloc(dst_n + (src_n * dollars) + 1);
char *ptr = res;
return res;
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];
}
}
}
*ptr++ = 0;
return res;
}
#endif
+5 -5
View File
@@ -630,7 +630,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
}
#ifdef __linux__
long somaxconn = uwsgi_num_from_file("/proc/sys/net/core/somaxconn");
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 (%i).\n", somaxconn);
uwsgi_nuclear_blast();
@@ -1611,7 +1611,7 @@ void uwsgi_map_sockets() {
exit(1);
}
if (fd != uwsgi_sock->fd) {
if (dup2(fd, uwsgi_sock->fd)) {
if (dup2(fd, uwsgi_sock->fd) < 0) {
uwsgi_error("dup2()");
exit(1);
}
@@ -1702,14 +1702,14 @@ void uwsgi_bind_sockets() {
gsa.sa = (struct sockaddr *) &usa;
if (!uwsgi.skip_zero && !getsockname(0, gsa.sa, &socket_type_len)) {
if (gsa.sa->sa_family == AF_UNIX) {
uwsgi_sock = uwsgi_new_socket(usa.sa_un.sun_path);
uwsgi_sock = uwsgi_new_socket(uwsgi_getsockname(0));
uwsgi_sock->family = AF_UNIX;
uwsgi_sock->fd = 0;
uwsgi_sock->bound = 1;
uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
else {
uwsgi_sock = uwsgi_new_socket(uwsgi_concat2("::", ""));
uwsgi_sock = uwsgi_new_socket(uwsgi_getsockname(0));
uwsgi_sock->family = AF_INET;
uwsgi_sock->fd = 0;
uwsgi_sock->bound = 1;
@@ -1723,7 +1723,7 @@ void uwsgi_bind_sockets() {
exit(1);
}
if (fd != 0) {
if (dup2(fd, 0)) {
if (dup2(fd, 0) < 0) {
uwsgi_error("dup2()");
exit(1);
}
+10
View File
@@ -97,8 +97,18 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
exit(1);
}
else if (pid == 0) {
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
// USR1 will be used to wake up the spooler
uwsgi_unix_signal(SIGUSR1, spooler_wakeup);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.mywid = -1;
uwsgi.mypid = getpid();
uspool->pid = uwsgi.mypid;
+16 -8
View File
@@ -373,7 +373,7 @@ struct uwsgi_stats_pusher *uwsgi_stats_pusher_get(char *name) {
return usp;
}
void 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;
@@ -389,6 +389,8 @@ void uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *pusher, char *arg) {
else {
uwsgi.stats_pusher_instances = uspi;
}
return uspi;
}
void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
@@ -413,12 +415,16 @@ void uwsgi_stats_pusher_loop(struct uwsgi_thread *ut) {
while (uspi) {
int delta = uspi->freq ? uspi->freq : uwsgi.stats_pusher_default_freq;
if ((uspi->last_run + delta) <= now) {
if (!us) {
us = uwsgi_master_generate_stats();
if (!us)
goto next;
if (uspi->raw) {
uspi->pusher->func(uspi, now, NULL, 0);
}
else {
if (!us) {
us = uwsgi_master_generate_stats();
if (!us) goto next;
}
uspi->pusher->func(uspi, now, us->base, us->pos);
}
uspi->pusher->func(uspi, us->base, us->pos);
uspi->last_run = now;
}
next:
@@ -456,7 +462,7 @@ void uwsgi_stats_pusher_setup() {
}
}
void uwsgi_register_stats_pusher(char *name, void (*func) (struct uwsgi_stats_pusher_instance *, char *, size_t)) {
struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *name, void (*func) (struct uwsgi_stats_pusher_instance *, time_t, char *, size_t)) {
struct uwsgi_stats_pusher *pusher = uwsgi.stats_pushers, *old_pusher = NULL;
@@ -475,6 +481,8 @@ void uwsgi_register_stats_pusher(char *name, void (*func) (struct uwsgi_stats_pu
else {
uwsgi.stats_pushers = pusher;
}
return pusher;
}
struct uwsgi_stats_pusher_file_conf {
@@ -483,7 +491,7 @@ struct uwsgi_stats_pusher_file_conf {
char *separator;
};
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, char *json, size_t json_len) {
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
if (!uspi->configured) {
uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
+124 -27
View File
@@ -848,17 +848,19 @@ void uwsgi_linux_ksm_map(void) {
#endif
#ifdef __linux__
long uwsgi_num_from_file(char *filename) {
long uwsgi_num_from_file(char *filename, int quiet) {
char buf[16];
ssize_t len;
int fd = open(filename, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(filename);
if (!quiet)
uwsgi_error_open(filename);
return -1L;
}
len = read(fd, buf, sizeof(buf));
if (len == 0) {
uwsgi_log("read error %s\n", filename);
if (!quiet)
uwsgi_log("read error %s\n", filename);
close(fd);
return -1L;
}
@@ -2030,6 +2032,24 @@ int uwsgi_logic_opt_for(char *key, char *value) {
return 1;
}
int uwsgi_logic_opt_for_glob(char *key, char *value) {
glob_t g;
int i;
if (glob(uwsgi.logic_opt_data, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("uwsgi_logic_opt_for_glob()");
return 0;
}
for (i = 0; i < (int) g.gl_pathc; i++) {
add_exported_option(key, uwsgi_substitute(value, "%(_)", g.gl_pathv[i]), 0);
}
globfree(&g);
return 1;
}
void add_exported_option(char *key, char *value, int configured) {
struct uwsgi_string_list *blacklist = uwsgi.blacklist;
@@ -2894,7 +2914,7 @@ size_t uwsgi_str_num(char *str, int len) {
int i;
size_t num = 0;
size_t delta = pow(10, len);
uint64_t delta = pow(10, len);
for (i = 0; i < len; i++) {
delta = delta / 10;
@@ -3307,7 +3327,7 @@ pid_t uwsgi_run_command(char *command, int *stdin_fd, int stdout_fd) {
}
else {
if (in_fd != 0) {
if (dup2(in_fd, 0)) {
if (dup2(in_fd, 0) < 0) {
uwsgi_error("dup2()");
}
}
@@ -4107,31 +4127,53 @@ struct uwsgi_app *uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int
char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) {
struct uwsgi_string_list *touch = touch_list;
while (touch) {
struct stat tr_st;
if (stat(touch->value, &tr_st)) {
uwsgi_log("unable to stat() %s, events will be triggered as soon as the file is created\n", touch->value);
touch->custom = 0;
}
else {
if (!touch->custom)
touch->custom = (uint64_t) tr_st.st_mtime;
if ((uint64_t) tr_st.st_mtime > touch->custom) {
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-check-touches] modification detected on %s: %llu -> %llu\n", touch->value, (unsigned long long) touch->custom, (unsigned long long) tr_st.st_mtime);
#endif
touch->custom = (uint64_t) tr_st.st_mtime;
return touch->value;
}
touch->custom = (uint64_t) tr_st.st_mtime;
}
touch = touch->next;
}
// touch->value - file path
// touch->custom - file timestamp
// touch->custom2 - 0 if file exists, 1 if it does not exists
return NULL;
struct uwsgi_string_list *touch = touch_list;
while (touch) {
struct stat tr_st;
if (stat(touch->value, &tr_st)) {
if (touch->custom && !touch->custom2) {
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-check-touches] File %s was removed\n", touch->value);
#endif
touch->custom2 = 1;
return touch->value;
}
else if (!touch->custom && !touch->custom2) {
uwsgi_log("unable to stat() %s, events will be triggered as soon as the file is created\n", touch->value);
touch->custom2 = 1;
}
touch->custom = 0;
}
else {
if (!touch->custom && touch->custom2) {
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-check-touches] File was created: %s\n", touch->value);
#endif
touch->custom = (uint64_t) tr_st.st_mtime;
touch->custom2 = 0;
return touch->value;
}
else if (touch->custom && (uint64_t) tr_st.st_mtime > touch->custom) {
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-check-touches] modification detected on %s: %llu -> %llu\n", touch->value, (unsigned long long) touch->custom, (unsigned long long) tr_st.st_mtime);
#endif
touch->custom = (uint64_t) tr_st.st_mtime;
return touch->value;
}
touch->custom = (uint64_t) tr_st.st_mtime;
}
touch = touch->next;
}
return NULL;
}
char *uwsgi_chomp(char *str) {
size_t i;
for (i = 0; i < strlen(str); i++) {
@@ -5095,3 +5137,58 @@ void uwsgi_close_all_fds(void) {
}
}
/*
even if it is marked as non-blocking, so not use in request plugins as it uses poll() and not the hooks
*/
int uwsgi_write_nb(int fd, char *buf, size_t remains, int timeout) {
char *ptr = buf;
while(remains > 0) {
int ret = uwsgi_waitfd_write(fd, timeout);
if (ret > 0) {
ssize_t len = write(fd, ptr, remains);
if (len <= 0) {
return -1;
}
ptr += len;
remains -= len;
continue;
}
return -1;
}
return 0;
}
// create a message pipe
void create_msg_pipe(int *fd, int bufsize) {
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fd)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fd)) {
#endif
uwsgi_error("create_msg_pipe()/socketpair()");
exit(1);
}
uwsgi_socket_nb(fd[0]);
uwsgi_socket_nb(fd[1]);
if (bufsize) {
if (setsockopt(fd[0], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
if (setsockopt(fd[0], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
if (setsockopt(fd[1], SOL_SOCKET, SO_SNDBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
if (setsockopt(fd[1], SOL_SOCKET, SO_RCVBUF, &bufsize, sizeof(int))) {
uwsgi_error("create_msg_pipe()/setsockopt()");
}
}
}
+69 -7
View File
@@ -2,7 +2,7 @@
*** uWSGI ***
Copyright (C) 2009-2012 Unbit S.a.s. <info@unbit.it>
Copyright (C) 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
@@ -38,6 +38,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"socket", required_argument, 's', "bind to the specified UNIX/TCP socket using default protocol", uwsgi_opt_add_socket, NULL, 0},
{"uwsgi-socket", required_argument, 's', "bind to the specified UNIX/TCP socket using uwsgi protocol", uwsgi_opt_add_socket, "uwsgi", 0},
{"http-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using HTTP protocol", uwsgi_opt_add_socket, "http", 0},
{"http-socket-modifier1", required_argument, 0, "force the specified modifier1 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier1, 0},
{"http-socket-modifier2", required_argument, 0, "force the specified modifier2 when using HTTP protocol", uwsgi_opt_set_64bit, &uwsgi.http_modifier2, 0},
{"fastcgi-socket", required_argument, 0, "bind to the specified UNIX/TCP socket using FastCGI protocol", uwsgi_opt_add_socket, "fastcgi", 0},
{"protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
{"socket-protocol", required_argument, 0, "force the specified protocol for default sockets", uwsgi_opt_set_str, &uwsgi.protocol, 0},
@@ -45,12 +47,13 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"undeferred-shared-socket", required_argument, 0, "create a shared sacket for advanced jailing or ipc (undeferred mode)", uwsgi_opt_add_shared_socket, NULL, 0},
{"processes", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
{"workers", required_argument, 'p', "spawn the specified number of workers/processes", uwsgi_opt_set_int, &uwsgi.numproc, 0},
{"thunder-lock", no_argument, 0, "serialize accept() usage (if possibie)", uwsgi_opt_true, &uwsgi.use_thunder_lock, 0},
{"harakiri", required_argument, 't', "set harakiri timeout", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_HARAKIRI, 0},
{"harakiri-verbose", no_argument, 0, "enable verbose mode for harakiri", uwsgi_opt_true, &uwsgi.harakiri_verbose, 0},
{"harakiri-no-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
{"no-harakiri-arh", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
{"no-harakiri-after-req-hook", no_argument, 0, "do not enable harakiri during after-request-hook", uwsgi_opt_true, &uwsgi.harakiri_no_arh, 0},
{"backtrace-depth", no_argument, 0, "set backtrace depth", uwsgi_opt_set_int, &uwsgi.backtrace_depth, 0},
{"backtrace-depth", required_argument, 0, "set backtrace depth", uwsgi_opt_set_int, &uwsgi.backtrace_depth, 0},
{"mule-harakiri", required_argument, 0, "set harakiri timeout for mule tasks", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_MULE_HARAKIRI, 0},
#ifdef UWSGI_XML
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
@@ -63,6 +66,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"declare-option", required_argument, 0, "declare a new uWSGI custom option", uwsgi_opt_add_custom_option, NULL, UWSGI_OPT_IMMEDIATE},
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
{"for-glob", required_argument, 0, "(opt logic) for cycle (expand glob)", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for_glob, UWSGI_OPT_IMMEDIATE},
{"endfor", optional_argument, 0, "(opt logic) end for cycle", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
{"if-opt", required_argument, 0, "(opt logic) check for option", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_opt, UWSGI_OPT_IMMEDIATE},
@@ -105,7 +109,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"suspend", required_argument, 0, "suspend an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP, UWSGI_OPT_IMMEDIATE},
{"resume", required_argument, 0, "resume an instance", uwsgi_opt_pidfile_signal, (void *) SIGTSTP, UWSGI_OPT_IMMEDIATE},
{"connect-and-read", required_argument, 0, "connect to a scoekt and wait for data from it", uwsgi_opt_connect_and_read, NULL, UWSGI_OPT_IMMEDIATE},
{"connect-and-read", required_argument, 0, "connect to a socket and wait for data from it", uwsgi_opt_connect_and_read, NULL, UWSGI_OPT_IMMEDIATE},
{"extract", required_argument, 0, "fetch/dump any supported address to stdout", uwsgi_opt_extract, NULL, UWSGI_OPT_IMMEDIATE},
{"listen", required_argument, 'l', "set the socket listen queue size", uwsgi_opt_set_int, &uwsgi.listen_queue, 0},
{"max-vars", required_argument, 'v', "set the amount of internal iovec/vars structures", uwsgi_opt_max_vars, NULL, 0},
@@ -139,6 +144,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"need-app", no_argument, 0, "exit if no app can be loaded", uwsgi_opt_true, &uwsgi.need_app, 0},
{"master", no_argument, 'M', "enable master process", uwsgi_opt_true, &uwsgi.master_process, 0},
{"emperor", required_argument, 0, "run the Emperor", uwsgi_opt_add_string_list, &uwsgi.emperor, 0},
{"emperor-procname", required_argument, 0, "set the Emperor process name", uwsgi_opt_set_str, &uwsgi.emperor_procname, 0},
{"emperor-freq", required_argument, 0, "set the Emperor scan frequency (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.emperor_freq, 0},
{"emperor-required-heartbeat", required_argument, 0, "set the Emperor tolerance about heartbeats", uwsgi_opt_set_int, &uwsgi.emperor_heartbeat, 0},
{"emperor-pidfile", required_argument, 0, "write the Emperor pid in the specified file", uwsgi_opt_set_str, &uwsgi.emperor_pidfile, 0},
@@ -202,6 +208,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"mule", optional_argument, 0, "add a mule", uwsgi_opt_add_mule, NULL, UWSGI_OPT_MASTER},
{"mules", required_argument, 0, "add the specified number of mules", uwsgi_opt_add_mules, NULL, UWSGI_OPT_MASTER},
{"farm", required_argument, 0, "add a mule farm", uwsgi_opt_add_farm, NULL, UWSGI_OPT_MASTER},
{"mule-msg-size", optional_argument, 0, "set mule message buffer size", uwsgi_opt_set_int, &uwsgi.mule_msg_size, UWSGI_OPT_MASTER},
{"signal", required_argument, 0, "send a uwsgi signal to a server", uwsgi_opt_signal, NULL, UWSGI_OPT_IMMEDIATE},
{"signal-bufsize", required_argument, 0, "set buffer size for signal queue", uwsgi_opt_set_int, &uwsgi.signal_bufsize, 0},
@@ -377,6 +384,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"alarm", required_argument, 0, "create a new alarm, syntax: <alarm> <plugin:args>", uwsgi_opt_add_string_list, &uwsgi.alarm_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"alarm-freq", required_argument, 0, "tune the anti-loop alam system (default 3 seconds)", uwsgi_opt_set_int, &uwsgi.alarm_freq, 0},
{"log-alarm", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"alarm-log", required_argument, 0, "raise the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"not-log-alarm", required_argument, 0, "skip the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list_custom, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"not-alarm-log", required_argument, 0, "skip the specified alarm when a log line matches the specified regexp, syntax: <alarm>[,alarm...] <regexp>", uwsgi_opt_add_string_list_custom, &uwsgi.alarm_logs_list, UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
{"alarm-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
{"alarms-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
#endif
@@ -1660,6 +1670,14 @@ int main(int argc, char *argv[], char *envp[]) {
struct utsname uuts;
// signal mask is inherited, and sme process manager could make a real mess...
sigset_t smask;
sigfillset(&smask);
if (sigprocmask(SIG_UNBLOCK, &smask, NULL)) {
uwsgi_error("sigprocmask()");
}
signal(SIGCHLD, SIG_DFL);
signal(SIGSEGV, uwsgi_segfault);
signal(SIGFPE, uwsgi_fpe);
signal(SIGHUP, SIG_IGN);
@@ -2327,9 +2345,9 @@ int uwsgi_start(void *v_argv) {
#endif
#ifdef UWSGI_UDP
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.udp_socket && !uwsgi.emperor && !uwsgi.command_mode) {
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.udp_socket && !uwsgi.emperor && !uwsgi.command_mode && !uwsgi.daemons_cnt) {
#else
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.emperor && !uwsgi.command_mode) {
if (!uwsgi.sockets && !ushared->gateways_cnt && !uwsgi.no_server && !uwsgi.emperor && !uwsgi.command_mode && !uwsgi.daemons_cnt) {
#endif
uwsgi_log("The -s/--socket option is missing and stdin is not a socket.\n");
exit(1);
@@ -2690,7 +2708,7 @@ next2:
}
if (uwsgi.sockets->fd != 0) {
if (dup2(uwsgi.sockets->fd, 0)) {
if (dup2(uwsgi.sockets->fd, 0) < 0) {
uwsgi_error("dup2()");
}
}
@@ -2888,7 +2906,7 @@ wait_for_call_of_duty:
uwsgi_ignition();
}
// never here
pthread_exit(NULL);
end_me(0);
}
/*
@@ -3294,6 +3312,35 @@ void uwsgi_opt_add_string_list(char *opt, char *value, void *list) {
uwsgi_string_new_list(ptr, value);
}
void uwsgi_opt_add_addr_list(char *opt, char *value, void *list) {
struct uwsgi_string_list **ptr = (struct uwsgi_string_list **) list;
int af = AF_INET;
#ifdef UWSGI_IPV6
void *ip = uwsgi_malloc(16);
if (strchr(value, ':')) {
af = AF_INET6;
}
#else
void *ip = uwsgi_malloc(4);
#endif
if (inet_pton(af, value, ip) <= 0) {
uwsgi_log("%s: invalid address\n", opt);
uwsgi_error("uwsgi_opt_add_addr_list()");
exit(1);
}
struct uwsgi_string_list *usl = uwsgi_string_new_list(ptr, ip);
usl->custom = af;
usl->custom_ptr = value;
}
void uwsgi_opt_add_string_list_custom(char *opt, char *value, void *list) {
struct uwsgi_string_list **ptr = (struct uwsgi_string_list **) list;
struct uwsgi_string_list *usl = uwsgi_string_new_list(ptr, value);
usl->custom = 1;
}
#ifdef UWSGI_PCRE
void uwsgi_opt_add_regexp_list(char *opt, char *value, void *list) {
struct uwsgi_regexp_list **ptr = (struct uwsgi_regexp_list **) list;
@@ -3879,3 +3926,18 @@ void uwsgi_opt_connect_and_read(char *opt, char *address, void *foobar) {
uwsgi_log("%.*s", (int) len, buf);
}
}
void uwsgi_opt_extract(char *opt, char *address, void *foobar) {
int len = 0;
char *buf;
buf = uwsgi_open_and_read(address, &len, 0, NULL);
if (len > 0) {
if (write(1, buf, len) != len) {
uwsgi_error("write()");
exit(1);
};
};
exit(0);
}
+1 -1
View File
@@ -137,7 +137,7 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
exit(1);
}
yaml_parser_set_input_string(&parser, (const unsigned char *) yaml, (size_t) len - 1);
yaml_parser_set_input_string(&parser, (unsigned char *) yaml, (size_t) len - 1);
while (parsing) {
if (!yaml_parser_scan(&parser, &token)) {
+15
View File
@@ -0,0 +1,15 @@
require 'net/http'
Net::HTTP.start("uwsgi.it") do |http|
resp = http.get("/install")
open("install.sh", "wb") do |file|
file.write(resp.body)
end
end
system("bash install.sh rack #{Dir.pwd}/uwsgi.ruby")
open("Makefile", "w") do |file|
file.write("all:\n")
file.write("\t\n")
end
-309
View File
@@ -1,309 +0,0 @@
/*
*** uWSGI, stripped down version of Linux rbtree ***
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
(C) 2002 David Woodhouse <dwmw2@infradead.org>
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../uwsgi.h"
static inline void rb_set_parent(struct rb_node *rb, struct rb_node *p)
{
rb->rb_parent_color = (rb->rb_parent_color & 3) | (unsigned long)p;
}
static inline void rb_set_color(struct rb_node *rb, int color)
{
rb->rb_parent_color = (rb->rb_parent_color & ~1) | color;
}
static void __rb_rotate_left(struct rb_node *node, struct rb_root *root)
{
struct rb_node *right = node->rb_right;
struct rb_node *parent = rb_parent(node);
if ((node->rb_right = right->rb_left))
rb_set_parent(right->rb_left, node);
right->rb_left = node;
rb_set_parent(right, parent);
if (parent)
{
if (node == parent->rb_left)
parent->rb_left = right;
else
parent->rb_right = right;
}
else
root->rb_node = right;
rb_set_parent(node, right);
}
static void __rb_rotate_right(struct rb_node *node, struct rb_root *root)
{
struct rb_node *left = node->rb_left;
struct rb_node *parent = rb_parent(node);
if ((node->rb_left = left->rb_right))
rb_set_parent(left->rb_right, node);
left->rb_right = node;
rb_set_parent(left, parent);
if (parent)
{
if (node == parent->rb_right)
parent->rb_right = left;
else
parent->rb_left = left;
}
else
root->rb_node = left;
rb_set_parent(node, left);
}
void rb_insert_color(struct rb_node *node, struct rb_root *root)
{
struct rb_node *parent, *gparent;
while ((parent = rb_parent(node)) && rb_is_red(parent))
{
gparent = rb_parent(parent);
if (parent == gparent->rb_left)
{
{
register struct rb_node *uncle = gparent->rb_right;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_right == node)
{
register struct rb_node *tmp;
__rb_rotate_left(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_right(gparent, root);
} else {
{
register struct rb_node *uncle = gparent->rb_left;
if (uncle && rb_is_red(uncle))
{
rb_set_black(uncle);
rb_set_black(parent);
rb_set_red(gparent);
node = gparent;
continue;
}
}
if (parent->rb_left == node)
{
register struct rb_node *tmp;
__rb_rotate_right(parent, root);
tmp = parent;
parent = node;
node = tmp;
}
rb_set_black(parent);
rb_set_red(gparent);
__rb_rotate_left(gparent, root);
}
}
rb_set_black(root->rb_node);
}
static void __rb_erase_color(struct rb_node *node, struct rb_node *parent,
struct rb_root *root)
{
struct rb_node *other;
while ((!node || rb_is_black(node)) && node != root->rb_node)
{
if (parent->rb_left == node)
{
other = parent->rb_right;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_left(parent, root);
other = parent->rb_right;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_right || rb_is_black(other->rb_right))
{
rb_set_black(other->rb_left);
rb_set_red(other);
__rb_rotate_right(other, root);
other = parent->rb_right;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_right);
__rb_rotate_left(parent, root);
node = root->rb_node;
break;
}
}
else
{
other = parent->rb_left;
if (rb_is_red(other))
{
rb_set_black(other);
rb_set_red(parent);
__rb_rotate_right(parent, root);
other = parent->rb_left;
}
if ((!other->rb_left || rb_is_black(other->rb_left)) &&
(!other->rb_right || rb_is_black(other->rb_right)))
{
rb_set_red(other);
node = parent;
parent = rb_parent(node);
}
else
{
if (!other->rb_left || rb_is_black(other->rb_left))
{
rb_set_black(other->rb_right);
rb_set_red(other);
__rb_rotate_left(other, root);
other = parent->rb_left;
}
rb_set_color(other, rb_color(parent));
rb_set_black(parent);
rb_set_black(other->rb_left);
__rb_rotate_right(parent, root);
node = root->rb_node;
break;
}
}
}
if (node)
rb_set_black(node);
}
void rb_erase(struct rb_node *node, struct rb_root *root)
{
struct rb_node *child, *parent;
int color;
if (!node->rb_left)
child = node->rb_right;
else if (!node->rb_right)
child = node->rb_left;
else
{
struct rb_node *old = node, *left;
node = node->rb_right;
while ((left = node->rb_left) != NULL)
node = left;
if (rb_parent(old)) {
if (rb_parent(old)->rb_left == old)
rb_parent(old)->rb_left = node;
else
rb_parent(old)->rb_right = node;
} else
root->rb_node = node;
child = node->rb_right;
parent = rb_parent(node);
color = rb_color(node);
if (parent == old) {
parent = node;
} else {
if (child)
rb_set_parent(child, parent);
parent->rb_left = child;
node->rb_right = old->rb_right;
rb_set_parent(old->rb_right, node);
}
node->rb_parent_color = old->rb_parent_color;
node->rb_left = old->rb_left;
rb_set_parent(old->rb_left, node);
goto color;
}
parent = rb_parent(node);
color = rb_color(node);
if (child)
rb_set_parent(child, parent);
if (parent)
{
if (parent->rb_left == node)
parent->rb_left = child;
else
parent->rb_right = child;
}
else
root->rb_node = child;
color:
if (color == RB_BLACK)
__rb_erase_color(child, parent, root);
}
#ifdef __clang__
void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#else
inline void rb_link_node(struct rb_node * node, struct rb_node * parent,
struct rb_node ** rb_link)
#endif
{
node->rb_parent_color = (unsigned long )parent;
node->rb_left = node->rb_right = NULL;
*rb_link = node;
}
+15 -1
View File
@@ -1,5 +1,6 @@
#include "../../uwsgi.h"
#include <gloox/client.h>
#include <gloox/error.h>
#include <gloox/message.h>
#include <gloox/connectionlistener.h>
#include <gloox/connectiontcpclient.h>
@@ -51,11 +52,14 @@ class Jabbo : public ConnectionListener{
event_queue_add_fd_read(u_thread->queue, fd);
event_queue_add_fd_read(u_thread->queue, u_thread->pipe[1]);
u_connected = 1;
uwsgi_log("[uwsgi-xmpp] connected to the XMPP server\n");
}
virtual void onDisconnect(ConnectionError e) {
uwsgi_log("[uwsgi-xmpp] trying reconnect to the XMPP server...\n");
if (u_connected) {
event_queue_del_fd(u_thread->queue, fd, event_queue_read());
// no need to remove it as it is already closed...
//event_queue_del_fd(u_thread->queue, fd, event_queue_read());
event_queue_del_fd(u_thread->queue, u_thread->pipe[1], event_queue_read());
}
sleep(1);
@@ -64,6 +68,16 @@ class Jabbo : public ConnectionListener{
fd = static_cast<ConnectionTCPClient*>( client->connectionImpl() )->socket();
}
virtual void onResourceBindError(const Error *error) {
uwsgi_log("[uwsgi-xmpp] onResourceBindError(): %s\n", error->text().c_str());
client->disconnect();
}
virtual void onSessionCreateError(const Error *error) {
uwsgi_log("[uwsgi-xmpp] onSessionCreateError(): %s\n", error->text().c_str());
client->disconnect();
}
virtual bool onTLSConnect(const CertInfo& info) {
return true;
}
+105 -50
View File
@@ -1,4 +1,10 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
/*
Author: Łukasz Mierzwa
*/
extern struct uwsgi_server uwsgi;
@@ -18,14 +24,19 @@ struct uwsgi_carbon {
int no_workers;
unsigned long long *last_busyness_values;
unsigned long long *current_busyness_values;
int *was_busy;
int need_retry;
time_t last_update;
time_t next_retry;
int max_retries;
int retry_delay;
char *root_node;
char *hostname_dot_replacement;
char *hostname;
struct uwsgi_stats_pusher *pusher;
} u_carbon;
struct uwsgi_option carbon_options[] = {
static struct uwsgi_option carbon_options[] = {
{"carbon", required_argument, 0, "push statistics to the specified carbon server", uwsgi_opt_add_string_list, &u_carbon.servers, UWSGI_OPT_MASTER},
{"carbon-timeout", required_argument, 0, "set carbon connection timeout in seconds (default 3)", uwsgi_opt_set_int, &u_carbon.timeout, 0},
{"carbon-freq", required_argument, 0, "set carbon push frequency in seconds (default 60)", uwsgi_opt_set_int, &u_carbon.freq, 0},
@@ -33,12 +44,13 @@ struct uwsgi_option carbon_options[] = {
{"carbon-no-workers", no_argument, 0, "disable generation of single worker metrics", uwsgi_opt_true, &u_carbon.no_workers, 0},
{"carbon-max-retry", required_argument, 0, "set maximum number of retries in case of connection errors (default 1)", uwsgi_opt_set_int, &u_carbon.max_retries, 0},
{"carbon-retry-delay", required_argument, 0, "set connection retry delay in seconds (default 7)", uwsgi_opt_set_int, &u_carbon.retry_delay, 0},
{"carbon-root", required_argument, 0, "set carbon metrics root node (default 'uwsgi')", uwsgi_opt_set_str, &u_carbon.root_node, 0},
{"carbon-hostname-dots", required_argument, 0, "set char to use as a replacement for dots in hostname (dots are not replaced by default)", uwsgi_opt_set_str, &u_carbon.hostname_dot_replacement, 0},
{0, 0, 0, 0, 0, 0, 0},
};
void carbon_post_init() {
static void carbon_post_init() {
int i;
struct uwsgi_string_list *usl = u_carbon.servers;
@@ -59,6 +71,11 @@ void carbon_post_init() {
usl = usl->next;
}
if (!u_carbon.root_node) u_carbon.root_node = "uwsgi.";
if (strlen(u_carbon.root_node) && !uwsgi_endswith(u_carbon.root_node, ".")) {
u_carbon.root_node = uwsgi_concat2(u_carbon.root_node, ".");
}
if (u_carbon.freq < 1) u_carbon.freq = 60;
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
@@ -71,22 +88,39 @@ void carbon_post_init() {
}
}
u_carbon.hostname = uwsgi_str(uwsgi.hostname);
if (u_carbon.hostname_dot_replacement) {
for(i=0;i<(int)strlen(u_carbon.hostname);i++) {
if (u_carbon.hostname[i] == '.') u_carbon.hostname[i] = u_carbon.hostname_dot_replacement[0];
}
}
if (!u_carbon.last_busyness_values) {
u_carbon.last_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
}
if (!u_carbon.current_busyness_values) {
u_carbon.current_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
}
if (!u_carbon.was_busy) {
u_carbon.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
}
// set next update to now()+retry_delay, this way we will have first flush just after start
u_carbon.last_update = uwsgi_now() - u_carbon.freq + u_carbon.retry_delay;
uwsgi_log("[carbon] carbon plugin started, %is frequency, %is timeout, max retries %i, retry delay %is\n",
u_carbon.freq, u_carbon.timeout, u_carbon.max_retries, u_carbon.retry_delay);
struct uwsgi_stats_pusher_instance *uspi = uwsgi_stats_pusher_add(u_carbon.pusher, NULL);
uspi->freq = u_carbon.freq;
// no need to generate the json
uspi->raw=1;
}
int carbon_write(int *fd, char *fmt,...) {
static int carbon_write(int fd, char *fmt,...) {
va_list ap;
va_start(ap, fmt);
@@ -94,19 +128,21 @@ int carbon_write(int *fd, char *fmt,...) {
int rlen;
rlen = vsnprintf(ptr, 4096, fmt, ap);
va_end(ap);
if (rlen < 1) return 0;
if (write(*fd, ptr, rlen) <= 0) {
uwsgi_error("write()");
if (uwsgi_write_nb(fd, ptr, rlen, u_carbon.timeout)) {
uwsgi_error("carbon_write()");
return 0;
}
return 1;
}
void carbon_push_stats(int retry_cycle) {
static void carbon_push_stats(int retry_cycle, time_t now) {
struct carbon_server_list *usl = u_carbon.servers_data;
if (!u_carbon.servers_data) return;
int i;
int fd;
int wok;
@@ -114,6 +150,7 @@ void carbon_push_stats(int retry_cycle) {
for (i = 0; i < uwsgi.numproc; i++) {
u_carbon.current_busyness_values[i] = uwsgi.workers[i+1].running_time - u_carbon.last_busyness_values[i];
u_carbon.last_busyness_values[i] = uwsgi.workers[i+1].running_time;
u_carbon.was_busy[i-1] += uwsgi.workers[i+1].busy;
}
u_carbon.need_retry = 0;
@@ -137,7 +174,7 @@ void carbon_push_stats(int retry_cycle) {
u_carbon.need_retry = 1;
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
} else {
uwsgi_log("[carbon] Maximum number of retries for %s (1)\n",
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
usl->value, u_carbon.max_retries);
usl->healthy = 0;
usl->errors = 0;
@@ -160,11 +197,13 @@ void carbon_push_stats(int retry_cycle) {
unsigned long long worker_busyness = 0;
unsigned long long total_harakiri = 0;
wok = carbon_write(&fd, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) uwsgi.workers[0].requests, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) uwsgi.workers[0].requests, (unsigned long long) now);
if (!wok) goto clear;
for(i=1;i<=uwsgi.numproc;i++) {
total_tx += uwsgi.workers[i].tx;
total_harakiri += uwsgi.workers[i].harakiri_count;
if (uwsgi.workers[i].cheaped) {
// also if worker is cheaped than we report its average response time as zero, sending last value might be confusing
avg_rt = 0;
@@ -177,53 +216,63 @@ void carbon_push_stats(int retry_cycle) {
total_avg_rt += uwsgi.workers[i].avg_response_time;
// calculate worker busyness
worker_busyness = ((u_carbon.current_busyness_values[i-1]*100) / (u_carbon.freq*1000000));
if (worker_busyness > 100) worker_busyness = 100;
if (u_carbon.current_busyness_values[i-1] == 0 && u_carbon.was_busy[i-1]) {
worker_busyness = 100;
}
else {
worker_busyness = ((u_carbon.current_busyness_values[i-1]*100) / (u_carbon.freq*1000000));
if (worker_busyness > 100) worker_busyness = 100;
}
total_busyness += worker_busyness;
u_carbon.was_busy[i-1] = 0;
// only running workers are counted in total memory stats
total_rss += uwsgi.workers[i].rss_size;
total_vsz += uwsgi.workers[i].vsz_size;
total_harakiri += uwsgi.workers[i].harakiri_count;
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
// only running workers are counted in total memory stats and if memory-report option is enabled
total_rss += uwsgi.workers[i].rss_size;
total_vsz += uwsgi.workers[i].vsz_size;
}
}
//skip per worker metrics when disabled
if (u_carbon.no_workers) continue;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].requests, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.worker%d.requests %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].requests, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].rss_size, (unsigned long long) uwsgi.current_time);
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
wok = carbon_write(fd, "%s%s.%s.worker%d.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].rss_size, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(fd, "%s%s.%s.worker%d.vsz_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].vsz_size, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.worker%d.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].vsz_size, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.worker%d.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].tx, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) avg_rt, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.worker%d.busyness %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) worker_busyness, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].tx, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.busyness %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) worker_busyness, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.worker%d.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].harakiri_count, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.worker%d.harakiri %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, i, (unsigned long long) uwsgi.workers[i].harakiri_count, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(&fd, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_rss, (unsigned long long) uwsgi.current_time);
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1 || uwsgi.force_get_memusage) {
wok = carbon_write(fd, "%s%s.%s.rss_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_rss, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(fd, "%s%s.%s.vsz_size %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_vsz, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(fd, "%s%s.%s.avg_rt %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_vsz, (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) (active_workers ? total_avg_rt / active_workers : 0), (unsigned long long) uwsgi.current_time);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_tx, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.tx %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_tx, (unsigned long long) now);
if (!wok) goto clear;
if (active_workers > 0) {
@@ -232,18 +281,18 @@ void carbon_push_stats(int retry_cycle) {
} else {
total_avg_busyness = 0;
}
wok = carbon_write(&fd, "uwsgi.%s.%s.busyness %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_avg_busyness, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.busyness %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_avg_busyness, (unsigned long long) now);
if (!wok) goto clear;
wok = carbon_write(&fd, "uwsgi.%s.%s.active_workers %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) active_workers, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.active_workers %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) active_workers, (unsigned long long) now);
if (!wok) goto clear;
if (uwsgi.cheaper) {
wok = carbon_write(&fd, "uwsgi.%s.%s.cheaped_workers %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) uwsgi.numproc - active_workers, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.cheaped_workers %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) uwsgi.numproc - active_workers, (unsigned long long) now);
if (!wok) goto clear;
}
wok = carbon_write(&fd, "uwsgi.%s.%s.harakiri %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long) total_harakiri, (unsigned long long) uwsgi.current_time);
wok = carbon_write(fd, "%s%s.%s.harakiri %llu %llu\n", u_carbon.root_node, u_carbon.hostname, u_carbon.id, (unsigned long long) total_harakiri, (unsigned long long) now);
if (!wok) goto clear;
usl->healthy = 1;
@@ -260,28 +309,34 @@ nxt:
u_carbon.last_update -= u_carbon.timeout;
}
void carbon_master_cycle() {
static void carbon_push(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
if (!u_carbon.servers) return;
if (uwsgi.current_time - u_carbon.last_update >= u_carbon.freq || uwsgi.cleaning) {
if (u_carbon.need_retry && now >= u_carbon.next_retry) {
carbon_push_stats(1, now);
}
else {
// update
u_carbon.need_retry = 0;
carbon_push_stats(0);
} else if (u_carbon.need_retry && (uwsgi.current_time >= u_carbon.next_retry)) {
// retry failed servers
carbon_push_stats(1);
carbon_push_stats(0, now);
}
}
static void carbon_cleanup() {
carbon_push_stats(0, uwsgi_now());
}
static void carbon_register() {
u_carbon.pusher = uwsgi_register_stats_pusher("carbon", carbon_push);
}
struct uwsgi_plugin carbon_plugin = {
.name = "carbon",
.master_cleanup = carbon_master_cycle,
.master_cleanup = carbon_cleanup,
.options = carbon_options,
.master_cycle = carbon_master_cycle,
.on_load = carbon_register,
.post_init = carbon_post_init,
};
+22 -2
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
/*
@@ -13,6 +13,7 @@ struct uwsgi_cheaper_busyness_global {
uint64_t busyness_max;
uint64_t busyness_min;
uint64_t *last_values;
int *was_busy;
uint64_t tcheck;
uint64_t last_cheaped; // last time worker was cheaped due to low busyness
uint64_t next_cheap; // timestamp, we can cheap worker after it
@@ -140,6 +141,9 @@ int cheaper_busyness_algo(void) {
if (!uwsgi_cheaper_busyness_global.last_values) {
uwsgi_cheaper_busyness_global.last_values = uwsgi_calloc(sizeof(uint64_t) * uwsgi.numproc);
}
if (!uwsgi_cheaper_busyness_global.was_busy) {
uwsgi_cheaper_busyness_global.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
}
// set defaults
if (!uwsgi_cheaper_busyness_global.busyness_max) uwsgi_cheaper_busyness_global.busyness_max = 50;
@@ -179,6 +183,10 @@ int cheaper_busyness_algo(void) {
if (uwsgi.workers[i+1].cheaped == 0 && uwsgi.workers[i+1].pid > 0) {
active_workers++;
uwsgi_cheaper_busyness_global.was_busy[i] += uwsgi.workers[i+1].busy;
}
else {
uwsgi_cheaper_busyness_global.was_busy[i] = 0;
}
}
@@ -192,7 +200,19 @@ int cheaper_busyness_algo(void) {
for (i = 0; i < uwsgi.numproc; i++) {
if (uwsgi.workers[i+1].cheaped == 0 && uwsgi.workers[i+1].pid > 0) {
uint64_t percent = (( (uwsgi.workers[i+1].running_time-uwsgi_cheaper_busyness_global.last_values[i])*100)/t);
if (percent > 100) percent = 100;
if (percent > 100) {
percent = 100;
}
else if (uwsgi.workers[i+1].running_time-uwsgi_cheaper_busyness_global.last_values[i] == 0 && percent == 0 && uwsgi_cheaper_busyness_global.was_busy[i] > 0) {
// running_time did not change but workers were busy
// this means that workers had response times > busyness check interval
if (uwsgi_cheaper_busyness_global.verbose) {
uwsgi_log("[busyness] worker %d was busy %d time(s) in last cycle but no request was completed during this time, marking as 100%% busy\n",
i+1, uwsgi_cheaper_busyness_global.was_busy[i]);
}
percent = 100;
}
uwsgi_cheaper_busyness_global.was_busy[i] = 0;
total_busyness += percent;
if (uwsgi_cheaper_busyness_global.verbose && active_workers > 1)
uwsgi_log("[busyness] worker nr %d %llus average busyness is at %llu%%\n",
+7 -11
View File
@@ -327,16 +327,16 @@ static struct uwsgi_rb_timer *corerouter_reset_timeout(struct uwsgi_corerouter *
static void corerouter_expire_timeouts(struct uwsgi_corerouter *ucr) {
time_t current = uwsgi_now();
uint64_t current = (uint64_t) uwsgi_now();
struct uwsgi_rb_timer *urbt;
struct corerouter_session *cr_session;
for (;;) {
urbt = uwsgi_min_rb_timer(ucr->timeouts);
urbt = uwsgi_min_rb_timer(ucr->timeouts, NULL);
if (urbt == NULL)
return;
if (urbt->key <= current) {
if (urbt->value <= current) {
cr_session = (struct corerouter_session *) urbt->data;
cr_session->timed_out = 1;
if (cr_session->connecting) {
@@ -708,12 +708,12 @@ void uwsgi_corerouter_loop(int id, void *data) {
for (;;) {
// set timeouts and harakiri
min_timeout = uwsgi_min_rb_timer(ucr->timeouts);
min_timeout = uwsgi_min_rb_timer(ucr->timeouts, NULL);
if (min_timeout == NULL) {
delta = -1;
}
else {
delta = min_timeout->key - uwsgi_now();
delta = min_timeout->value - uwsgi_now();
if (delta <= 0) {
corerouter_expire_timeouts(ucr);
delta = 0;
@@ -833,12 +833,8 @@ void uwsgi_corerouter_loop(int id, void *data) {
}
}
if (!hook) {
uwsgi_log("[uwsgi-corerouter] BUG, unexpected event received !!!\n");
corerouter_close_session(ucr, cr_session);
continue;
}
// not having a hook could mean a previous event in the loop cleared it...
if (!hook) continue;
// reset errno (as we use it for internal signalling)
errno = 0;
ssize_t ret = hook(cr_session);
+3 -3
View File
@@ -6,8 +6,8 @@
#define cr_add_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, time(NULL)+u->socket_timeout, x)
#define cr_add_fake_timeout(u, x) uwsgi_add_rb_timer(u->timeouts, time(NULL)+1, x)
#define cr_add_check_timeout(x) uwsgi_add_rb_timer(timeouts, time(NULL)+x, NULL)
#define cr_del_check_timeout(x) rb_erase(&x->rbt, timeouts);
#define cr_del_timeout(u, x) rb_erase(&x->timeout->rbt, u->timeouts); free(x->timeout);
#define cr_del_check_timeout(x) uwsgi_del_rb_timer(timeouts, x);
#define cr_del_timeout(u, x) uwsgi_del_rb_timer(u->timeouts, x->timeout); free(x->timeout);
#define cr_try_again if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {\
errno = EINPROGRESS;\
@@ -33,7 +33,7 @@ struct uwsgi_corerouter {
int processes;
int quiet;
struct rb_root *timeouts;
struct uwsgi_rbtree *timeouts;
int use_cache;
int nevents;
+8
View File
@@ -59,6 +59,14 @@ void uwsgi_corerouter_setup_sockets(struct uwsgi_corerouter *ucr) {
uwsgi.no_defer_accept = current_defer_accept;
}
}
// fix SERVER_PORT
if (!ugs->port || !ugs->port_len) {
ugs->port = strchr(ugs->name, ':');
if (ugs->port) {
ugs->port++;
ugs->port_len = strlen(ugs->port);
}
}
// put socket in non-blocking mode
uwsgi_socket_nb(ugs->fd);
uwsgi_log("%s bound on %s fd %d\n", ucr->name, ugs->name, ugs->fd);
+15 -4
View File
@@ -230,7 +230,7 @@ ssize_t uwsgi_gevent_hook_input_read(struct wsgi_request *wsgi_req, char *tmp_bu
}
Py_DECREF(ret);
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
ret = PyObject_CallMethod(timer, "again", "OO", current, timer);
if (!ret) {
stop_the_watchers_and_clear
return -1;
@@ -253,6 +253,8 @@ ssize_t uwsgi_gevent_hook_input_read(struct wsgi_request *wsgi_req, char *tmp_bu
UWSGI_RELEASE_GIL;
ssize_t rlen = read(wsgi_req->poll.fd, tmp_buf+*tmp_pos, remains);
if (rlen <= 0) {
if (rlen < 0)
uwsgi_error("[uwsgi-gevent] read()");
UWSGI_GET_GIL
stop_the_watchers_and_clear
return -1;
@@ -263,6 +265,11 @@ ssize_t uwsgi_gevent_hook_input_read(struct wsgi_request *wsgi_req, char *tmp_bu
stop_the_watchers
}
Py_DECREF(current);
Py_DECREF(current_greenlet);
Py_DECREF(watcher);
Py_DECREF(timer);
return *tmp_pos;
}
@@ -291,7 +298,7 @@ ssize_t uwsgi_gevent_hook_input_readline(struct wsgi_request *wsgi_req, char *re
}
Py_DECREF(ret);
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
ret = PyObject_CallMethod(timer, "again", "OO", current, timer);
if (!ret) {
stop_the_watchers_and_clear
return -1;
@@ -328,6 +335,10 @@ void uwsgi_gevent_nb_write(struct wsgi_request *wsgi_req, PyObject *str) {
PyObject *ret;
char *content = PyString_AsString(str);
size_t content_len = PyString_Size(str);
// do not try to write empty chunks
if (content_len == 0) return;
/// create a watcher for writes
PyObject *watcher = PyObject_CallMethod(ugevent.hub_loop, "io", "ii", wsgi_req->poll.fd, 2);
if (!watcher) goto error;
@@ -353,7 +364,7 @@ void uwsgi_gevent_nb_write(struct wsgi_request *wsgi_req, PyObject *str) {
}
Py_DECREF(ret);
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
ret = PyObject_CallMethod(timer, "again", "OO", current, timer);
if (!ret) {
stop_the_watchers_and_clear
goto error;
@@ -420,7 +431,7 @@ PyObject *uwsgi_gevent_wait(PyObject *watcher, PyObject *timer, PyObject *curren
Py_DECREF(ret);
// start the timeout handler
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
ret = PyObject_CallMethod(timer, "again", "OO", current, timer);
if (!ret) return NULL;
Py_DECREF(ret);
+75 -27
View File
@@ -24,6 +24,7 @@ struct uwsgi_http {
#ifdef UWSGI_SSL
int https_export_cert;
#endif
struct uwsgi_string_list *stud_prefix;
} uhttp;
@@ -134,6 +135,7 @@ struct uwsgi_option http_options[] = {
{"http-stats-server", required_argument, 0, "run the http router stats server", uwsgi_opt_set_str, &uhttp.cr.stats_server, 0},
{"http-ss", required_argument, 0, "run the http router stats server", uwsgi_opt_set_str, &uhttp.cr.stats_server, 0},
{"http-harakiri", required_argument, 0, "enable http router harakiri", uwsgi_opt_set_int, &uhttp.cr.harakiri, 0},
{"http-stud-prefix", required_argument, 0, "expect a stud prefix (1byte family + 4/16 bytes address) on connections from the specified address", uwsgi_opt_add_addr_list, &uhttp.stud_prefix, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -175,6 +177,11 @@ struct http_session {
size_t post_buf_len;
off_t post_buf_pos;
// 1 (family) + 4/16 (addr)
char stud_prefix[17];
size_t stud_prefix_remains;
size_t stud_prefix_pos;
};
@@ -354,6 +361,11 @@ int http_parse(struct http_session *h_session, size_t http_req_len) {
// UWSGI_ROUTER
if (http_add_uwsgi_var(h_session, "UWSGI_ROUTER", 12, "http", 4)) return -1;
// stud HTTPS
if (h_session->stud_prefix_pos > 0) {
if (http_add_uwsgi_var(h_session, "HTTPS", 5, "on", 2)) return -1;
}
#ifdef UWSGI_SSL
// HTTPS (adapted from nginx)
if (h_session->cs.ugs->mode == UWSGI_HTTP_SSL) {
@@ -514,14 +526,14 @@ ssize_t hr_read_ssl_body(struct corerouter_session * cs) {
struct http_session *hs = (struct http_session *) cs;
int ret = SSL_read(hs->ssl, hs->post_buf->buf, hs->post_buf_max);
if (ret > 0) {
// fix waiting
if (cs->event_hook_write) {
uwsgi_cr_hook_write(cs, NULL);
}
int ret2 = SSL_pending(hs->ssl);
if (ret2 > 0) {
if (uwsgi_buffer_fix(hs->post_buf, hs->post_buf->len + ret2 )) return -1;
if (uwsgi_buffer_fix(hs->post_buf, hs->post_buf->len + ret2 )) {
uwsgi_log("[uwsgi-https] cannot fix the buffer to %d\n", hs->post_buf->len + ret2);
return -1;
}
if (SSL_read(hs->ssl, hs->post_buf->buf + ret, ret2) != ret2) {
uwsgi_log("[uwsgi-https] SSL_read() on %d bytes of pending data failed\n", ret2);
return -1;
}
ret += ret2;
@@ -539,8 +551,8 @@ ssize_t hr_read_ssl_body(struct corerouter_session * cs) {
if (err == SSL_ERROR_WANT_READ) {
if (cs->event_hook_write) {
uwsgi_cr_hook_write(cs, NULL);
uwsgi_cr_hook_read(cs, hr_read_ssl_body);
}
uwsgi_cr_hook_read(cs, hr_read_ssl_body);
errno = EINPROGRESS;
return -1;
}
@@ -548,8 +560,8 @@ ssize_t hr_read_ssl_body(struct corerouter_session * cs) {
else if (err == SSL_ERROR_WANT_WRITE) {
if (cs->event_hook_read) {
uwsgi_cr_hook_read(cs, NULL);
uwsgi_cr_hook_write(cs, hr_read_ssl_body);
}
uwsgi_cr_hook_write(cs, hr_read_ssl_body);
errno = EINPROGRESS;
return -1;
}
@@ -599,9 +611,6 @@ ssize_t hr_write_ssl_response(struct corerouter_session * cs) {
if (ret > 0) {
cs->buffer_pos += ret;
if (cs->event_hook_read) {
uwsgi_cr_hook_read(cs, NULL);
}
// could be a partial write
uwsgi_cr_hook_write(cs, hr_write_ssl_response);
// ok this response chunk is sent, let's wait for another one
@@ -616,16 +625,16 @@ ssize_t hr_write_ssl_response(struct corerouter_session * cs) {
if (err == SSL_ERROR_WANT_READ) {
if (cs->event_hook_write) {
uwsgi_cr_hook_write(cs, NULL);
uwsgi_cr_hook_read(cs, hr_write_ssl_response);
}
uwsgi_cr_hook_read(cs, hr_write_ssl_response);
errno = EINPROGRESS;
return -1;
}
else if (err == SSL_ERROR_WANT_WRITE) {
if (cs->event_hook_read) {
uwsgi_cr_hook_read(cs, NULL);
uwsgi_cr_hook_write(cs, hr_write_ssl_response);
}
uwsgi_cr_hook_write(cs, hr_write_ssl_response);
errno = EINPROGRESS;
return -1;
}
@@ -822,9 +831,6 @@ ssize_t hr_send_expect_continue(struct corerouter_session * cs) {
if (ret > 0) {
len = ret;
cs->buffer_pos += ret;
if (cs->event_hook_read) {
uwsgi_cr_hook_read(cs, NULL);
}
// could be a partial write
uwsgi_cr_hook_write(cs, hr_send_expect_continue);
goto done;
@@ -833,16 +839,16 @@ ssize_t hr_send_expect_continue(struct corerouter_session * cs) {
if (err == SSL_ERROR_WANT_READ) {
if (cs->event_hook_write) {
uwsgi_cr_hook_write(cs, NULL);
uwsgi_cr_hook_read(cs, hr_write_ssl_response);
}
uwsgi_cr_hook_read(cs, hr_write_ssl_response);
errno = EINPROGRESS;
return -1;
}
else if (err == SSL_ERROR_WANT_WRITE) {
if (cs->event_hook_read) {
uwsgi_cr_hook_read(cs, NULL);
uwsgi_cr_hook_write(cs, hr_write_ssl_response);
}
uwsgi_cr_hook_write(cs, hr_write_ssl_response);
errno = EINPROGRESS;
return -1;
}
@@ -916,19 +922,21 @@ ssize_t hr_recv_http_ssl(struct corerouter_session * cs) {
// be sure buffer does not grow over 64k
cs->buffer->limit = UMAX16;
// try to always leave 4k available
if (uwsgi_buffer_ensure(cs->buffer, uwsgi.page_size)) return -1;
if (uwsgi_buffer_ensure(cs->buffer, uwsgi.page_size)) {
uwsgi_log("[uwsgi-https] cannot ensure the buffer (size: %d)\n", cs->buffer->len);
return -1;
}
struct http_session *hs = (struct http_session *) cs;
int ret = SSL_read(hs->ssl, cs->buffer->buf + cs->buffer_pos, cs->buffer->len - cs->buffer_pos);
if (ret > 0) {
// fix waiting
if (cs->event_hook_write) {
uwsgi_cr_hook_write(cs, NULL);
uwsgi_cr_hook_read(cs, hr_recv_http_ssl);
}
int ret2 = SSL_pending(hs->ssl);
if (ret2 > 0) {
if (uwsgi_buffer_fix(cs->buffer, cs->buffer->len + ret2 )) return -1;
if (uwsgi_buffer_fix(cs->buffer, cs->buffer->len + ret2 )) {
uwsgi_log("[uwsgi-https] cannot fix the buffer to %d\n", cs->buffer->len + ret2 );
return -1;
}
if (SSL_read(hs->ssl, cs->buffer->buf + cs->buffer_pos + ret, ret2) != ret2) {
uwsgi_log("[uwsgi-https] SSL_read() on %d bytes of pending data failed\n", ret2);
return -1;
}
ret += ret2;
@@ -941,8 +949,8 @@ ssize_t hr_recv_http_ssl(struct corerouter_session * cs) {
if (err == SSL_ERROR_WANT_READ) {
if (cs->event_hook_write) {
uwsgi_cr_hook_write(cs, NULL);
uwsgi_cr_hook_read(cs, hr_recv_http_ssl);
}
uwsgi_cr_hook_read(cs, hr_recv_http_ssl);
errno = EINPROGRESS;
return -1;
}
@@ -950,8 +958,8 @@ ssize_t hr_recv_http_ssl(struct corerouter_session * cs) {
else if (err == SSL_ERROR_WANT_WRITE) {
if (cs->event_hook_read) {
uwsgi_cr_hook_read(cs, NULL);
uwsgi_cr_hook_write(cs, hr_recv_http_ssl);
}
uwsgi_cr_hook_write(cs, hr_recv_http_ssl);
errno = EINPROGRESS;
return -1;
}
@@ -1071,6 +1079,31 @@ void hr_session_close(struct corerouter_session *cs) {
}
}
static ssize_t hr_recv_stud4(struct corerouter_session * cs) {
struct http_session *hs = (struct http_session *) cs;
ssize_t len = read(cs->fd, hs->stud_prefix + hs->stud_prefix_pos, hs->stud_prefix_remains - hs->stud_prefix_pos);
if (len < 0) {
cr_try_again;
uwsgi_error("hr_recv_stud4()");
return -1;
}
hs->stud_prefix_pos += len;
if (hs->stud_prefix_pos == hs->stud_prefix_remains) {
if (hs->stud_prefix[0] != AF_INET) {
uwsgi_log("[uwsgi-http] invalid stud prefix\n");
return -1;
}
// set the passed ip address
memcpy(&hs->ip_addr, hs->stud_prefix + 1, 4);
uwsgi_cr_hook_read(cs, hr_recv_http);
}
return len;
}
#ifdef UWSGI_SSL
void hr_session_ssl_close(struct corerouter_session *cs) {
hr_session_close(cs);
@@ -1092,6 +1125,8 @@ void hr_session_ssl_close(struct corerouter_session *cs) {
X509_free(hs->ssl_client_cert);
}
// clear the errors (otherwise they could be propagated)
ERR_clear_error();
SSL_free(hs->ssl);
}
#endif
@@ -1101,6 +1136,17 @@ void http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socke
cs->modifier1 = uhttp.modifier1;
if (sa && sa->sa_family == AF_INET) {
hs->ip_addr = ((struct sockaddr_in *) sa)->sin_addr.s_addr;
struct uwsgi_string_list *usl = uhttp.stud_prefix;
while(usl) {
if (!memcmp(&hs->ip_addr, usl->value, 4)) {
hs->stud_prefix_remains = 5;
uwsgi_cr_hook_read(cs, hr_recv_stud4);
break;
}
usl = usl->next;
}
}
hs->rnrn = 0;
@@ -1122,7 +1168,9 @@ void http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socke
}
else {
#endif
uwsgi_cr_hook_read(cs, hr_recv_http);
if (!cs->event_hook_read) {
uwsgi_cr_hook_read(cs, hr_recv_http);
}
cs->close = hr_session_close;
#ifdef UWSGI_SSL
}
-34
View File
@@ -1,34 +0,0 @@
#include "../../uwsgi.h"
#include <jni.h>
struct uwsgi_jvm {
struct uwsgi_string_list *classpath;
JNIEnv *env;
char *class;
jclass main_class;
jclass str_class;
jclass ht_class;
jclass fd_class;
};
jmethodID uwsgi_jvm_get_method_id(jclass, char *, char *);
jmethodID uwsgi_jvm_get_static_method_id(jclass, char *, char *);
jclass uwsgi_jvm_get_class(char *);
jclass uwsgi_jvm_get_object_class(jobject);
int uwsgi_jvm_exception(void);
jobject uwsgi_jvm_str_new(char *, int );
jobject uwsgi_jvm_str(char *);
jobject uwsgi_jvm_array_get(jobject , int );
jobject uwsgi_jvm_ht_new(void);
jobject uwsgi_jvm_ht_put(jobject, jobject, jobject);
jobject uwsgi_jvm_fd(int);
char *uwsgi_jvm_str2c(jobject);
int uwsgi_jvm_strlen2c(jobject);
-210
View File
@@ -1,210 +0,0 @@
#include "jvm.h"
/*
with javap -s -p <class>
you can get method signatures
This plugin is the core for all of the JVM-based ones
*/
struct uwsgi_jvm ujvm;
struct uwsgi_option uwsgi_jvm_options[] = {
{"jvm-main-class", required_argument, 0, "load the specified class", uwsgi_opt_set_str, &ujvm.class, 0},
{"jvm-classpath", required_argument, 0, "add the specified directory to the classpath", uwsgi_opt_add_string_list, &ujvm.classpath, 0},
{0, 0, 0, 0},
};
int uwsgi_jvm_exception(void) {
if ((*ujvm.env)->ExceptionOccurred(ujvm.env)) {
(*ujvm.env)->ExceptionDescribe(ujvm.env);
(*ujvm.env)->ExceptionClear(ujvm.env);
return 1;
}
return 0;
}
jclass uwsgi_jvm_get_object_class(jobject obj) {
return (*ujvm.env)->GetObjectClass(ujvm.env, obj);
}
jclass uwsgi_jvm_get_class(char *name) {
jclass my_class = (*ujvm.env)->FindClass(ujvm.env, name);
if (uwsgi_jvm_exception()) {
return NULL;
}
return my_class;
}
jmethodID uwsgi_jvm_get_method_id(jclass cls, char *name, char *signature) {
jmethodID mid;
mid = (*ujvm.env)->GetMethodID(ujvm.env, cls, name, signature);
return mid;
}
jmethodID uwsgi_jvm_get_static_method_id(jclass cls, char *name, char *signature) {
jmethodID mid;
mid = (*ujvm.env)->GetStaticMethodID(ujvm.env, cls, name, signature);
return mid;
}
jobject uwsgi_jvm_str_new(char *str, int len) {
jbyteArray ba;
static jmethodID str_new_mid = 0;
if (!str_new_mid) {
str_new_mid = uwsgi_jvm_get_method_id(ujvm.str_class, "<init>", "([BLjava/lang/String;)V");
}
ba = (*ujvm.env)->NewByteArray(ujvm.env, len);
(*ujvm.env)->SetByteArrayRegion(ujvm.env, ba, 0, len, (jbyte *) str);
return (*ujvm.env)->NewObject(ujvm.env, ujvm.str_class, str_new_mid, ba,
(*ujvm.env)->NewStringUTF(ujvm.env, "UTF-8"));
}
jobject uwsgi_jvm_str(char *str) {
return (*ujvm.env)->NewStringUTF(ujvm.env, str);
}
int jvm_init(void) {
jint res;
JavaVM *jvm;
JavaVMInitArgs vm_args;
JavaVMOption options[1];
jmethodID mmid;
char *old_cp = NULL ;
vm_args.version = JNI_VERSION_1_2;
JNI_GetDefaultJavaVMInitArgs(&vm_args);
options[0].optionString = "-Djava.class.path=.";
struct uwsgi_string_list *cp = ujvm.classpath;
while(cp) {
if (old_cp) {
options[0].optionString = uwsgi_concat3(old_cp, ":", cp->value);
free(old_cp);
}
else {
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", cp->value);
}
old_cp = options[0].optionString ;
cp = cp->next;
}
vm_args.options = options;
vm_args.nOptions = 1;
res = JNI_CreateJavaVM(&jvm, (void **) &ujvm.env, &vm_args);
if (res) {
uwsgi_log("unable to initialize JVM\n");
exit(1);
}
uwsgi_log("JVM initialized\n");
if (ujvm.class) {
ujvm.main_class = uwsgi_jvm_get_class(ujvm.class);
if (!ujvm.main_class) {
exit(1);
}
mmid = uwsgi_jvm_get_static_method_id(ujvm.main_class, "main", "([Ljava/lang/String;)V");
if (mmid) {
(*ujvm.env)->CallStaticVoidMethod(ujvm.env, ujvm.main_class, mmid);
uwsgi_jvm_exception();
}
}
ujvm.str_class = uwsgi_jvm_get_class("java/lang/String");
ujvm.ht_class = uwsgi_jvm_get_class("java/util/Hashtable");
ujvm.fd_class = uwsgi_jvm_get_class("java/io/FileDescriptor");
return 1;
}
jobject uwsgi_jvm_array_get(jobject obj, int index) {
return (*ujvm.env)->GetObjectArrayElement(ujvm.env, obj, index);
}
jobject uwsgi_jvm_ht_new() {
static jmethodID htimid = 0;
if (!htimid) {
htimid = uwsgi_jvm_get_method_id(ujvm.ht_class, "<init>", "()V");
}
return (*ujvm.env)->NewObject(ujvm.env, ujvm.ht_class, htimid);
}
jobject uwsgi_jvm_ht_put(jobject obj, jobject key, jobject val) {
static jmethodID htpmid = 0 ;
if (!htpmid) {
htpmid = uwsgi_jvm_get_method_id(ujvm.ht_class, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
}
return (*ujvm.env)->CallObjectMethod(ujvm.env, obj, htpmid, key, val);
}
jobject uwsgi_jvm_fd(int fd) {
jobject fd_obj;
static jmethodID fd_mid = 0;
static jfieldID fd_field = 0 ;
if (!fd_mid) {
fd_mid = uwsgi_jvm_get_method_id( ujvm.fd_class, "<init>", "()V");
}
fd_obj = (*ujvm.env)->NewObject(ujvm.env, ujvm.fd_class, fd_mid);
if (!fd_field) {
fd_field = (*ujvm.env)->GetFieldID(ujvm.env, ujvm.fd_class, "fd", "I");
}
(*ujvm.env)->SetIntField(ujvm.env, fd_obj, fd_field, fd);
return fd_obj;
}
char *uwsgi_jvm_str2c(jobject obj) {
return (char *) (*ujvm.env)->GetStringUTFChars(ujvm.env, obj, NULL);
}
int uwsgi_jvm_strlen2c(jobject obj) {
return (*ujvm.env)->GetStringUTFLength(ujvm.env, obj);
}
struct uwsgi_plugin jvm_plugin = {
.name = "jvm",
.init = jvm_init,
.options = uwsgi_jvm_options,
};
-47
View File
@@ -1,47 +0,0 @@
import os,sys
NAME='jvm'
# Snow Leopard
#JVM_INCPATH = "/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers/"
#JVM_LIBPATH = "/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Libraries/ -framework JavaVM"
# FreeBSD openjdk7 example
# env UWSGICONFIG_JVM_INCPATH="/usr/local/openjdk7/include -I/usr/local/openjdk7/include/freebsd/" UWSGICONFIG_JVM_LIBPATH="/usr/local/openjdk7/jre/lib/amd64/server" python uwsgiconfig.py --plugin plugins/jvm
# NexentaOS example
# UWSGICONFIG_JVM_INCPATH="/usr/java/include -I /usr/java/include/solaris" UWSGICONFIG_JVM_LIBPATH="/usr/java/jre/lib/i386/" python uwsgiconfig.py --plugin plugins/jvm
# Ubuntu
JVM_INCPATH = "/usr/lib/jvm/java-6-openjdk/include/ -I/usr/lib/jvm/java-6-openjdk/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server/"
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
except:
pass
try:
JVM_LIBPATH = os.environ['UWSGICONFIG_JVM_LIBPATH']
except:
pass
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
except:
pass
try:
JVM_LIBPATH = os.environ['UWSGICONFIG_JVM_LIBPATH']
except:
pass
CFLAGS = ['-I' + JVM_INCPATH]
LDFLAGS = ['-L' + JVM_LIBPATH]
LIBS = ['-ljvm']
GCC_LIST = ['jvm_plugin']
if os.environ.has_key('LD_RUN_PATH'):
os.environ['LD_RUN_PATH'] += ':' + JVM_LIBPATH
else:
os.environ['LD_RUN_PATH'] = JVM_LIBPATH
-117
View File
@@ -1,117 +0,0 @@
#include "../jvm/jvm.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_jvm ujvm;
void uwsgi_jwsgi_init(void) {
}
int uwsgi_jwsgi_request(struct wsgi_request *wsgi_req) {
jmethodID jmid;
int i;
jobject env;
jobject hkey, hval;
jobject response;
jobject status;
jobject headers, header;
jobject body;
jclass hc;
jmethodID hh_size, hh_get;
int hlen;
if (!wsgi_req->uh.pktsize) {
uwsgi_log("Invalid JWSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid JWSGI request. skip.\n");
return -1;
}
jmid = uwsgi_jvm_get_static_method_id(ujvm.main_class, "jwsgi", "(Ljava/util/Hashtable;)[Ljava/lang/Object;");
uwsgi_log("jwsgi method id = %d\n", jmid);
env = uwsgi_jvm_ht_new();
uwsgi_jvm_exception();
for(i=0;i<wsgi_req->var_cnt;i++) {
uwsgi_jvm_ht_put(env,
uwsgi_jvm_str_new(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
uwsgi_jvm_str_new(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len)
);
// check if something is going wrong during hashtable fill
uwsgi_jvm_exception();
i++;
}
uwsgi_log("env created\n");
uwsgi_jvm_ht_put(env, uwsgi_jvm_str("jwsgi.input"), uwsgi_jvm_fd(wsgi_req->poll.fd));
uwsgi_log("jwsgi.input created\n");
response = (*ujvm.env)->CallObjectMethod(ujvm.env, ujvm.main_class, jmid, env);
uwsgi_jvm_exception();
uwsgi_log("RESPONSE SIZE %d\n", (*ujvm.env)->GetArrayLength(ujvm.env, response));
status = uwsgi_jvm_array_get(response, 0);
uwsgi_jvm_exception();
wsgi_req->headers_size += write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " ", 1);
wsgi_req->headers_size += write(wsgi_req->poll.fd, uwsgi_jvm_str2c(status), uwsgi_jvm_strlen2c(status));
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
headers = uwsgi_jvm_array_get(response, 1);
hc = uwsgi_jvm_get_object_class(headers);
hh_size = uwsgi_jvm_get_method_id(hc, "size","()I");
hh_get = uwsgi_jvm_get_method_id(hc, "get","(I)Ljava/lang/Object;");
hlen = (*ujvm.env)->CallIntMethod(ujvm.env, headers, hh_size);
for(i=0;i<hlen;i++) {
header = (*ujvm.env)->CallObjectMethod(ujvm.env, headers, hh_get, i);
hkey = uwsgi_jvm_array_get(header, 0);
hval = uwsgi_jvm_array_get(header, 1);
wsgi_req->headers_size += write(wsgi_req->poll.fd, uwsgi_jvm_str2c(hkey), uwsgi_jvm_strlen2c(hkey));
wsgi_req->headers_size += write(wsgi_req->poll.fd, ": ", 2);
wsgi_req->headers_size += write(wsgi_req->poll.fd, uwsgi_jvm_str2c(hval), uwsgi_jvm_strlen2c(hval));
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
}
wsgi_req->headers_size += write(wsgi_req->poll.fd, "\r\n", 2);
body = uwsgi_jvm_array_get(response, 2);
wsgi_req->response_size = write(wsgi_req->poll.fd, (*ujvm.env)->GetStringUTFChars(ujvm.env, body, NULL), (*ujvm.env)->GetStringUTFLength(ujvm.env, body));
return 1;
}
void uwsgi_jwsgi_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
struct uwsgi_plugin jwsgi_plugin = {
.name = "jwsgi",
.modifier1 = 8,
.request = uwsgi_jwsgi_request,
.after_request = uwsgi_jwsgi_after_request,
};
-22
View File
@@ -1,22 +0,0 @@
import os,sys
NAME='jwsgi'
# Snow Leopard
#JVM_INCPATH = "/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Headers/"
#JVM_LIBPATH = "/Developer/SDKs/MacOSX10.6.sdk/System/Library/Frameworks/JavaVM.framework/Versions/1.6.0/Libraries/ -framework JavaVM"
# Ubuntu
JVM_INCPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/i386/server/"
CFLAGS = ['-I' + JVM_INCPATH]
LDFLAGS = ['-L' + JVM_LIBPATH]
LIBS = ['-ljvm']
GCC_LIST = ['jwsgi_plugin']
if os.environ.has_key('LD_RUN_PATH'):
os.environ['LD_RUN_PATH'] += ':' + JVM_LIBPATH
else:
os.environ['LD_RUN_PATH'] = JVM_LIBPATH
+113 -17
View File
@@ -133,30 +133,70 @@ static char *encode_lua_table(lua_State *L, int index, uint16_t *size) {
static int uwsgi_api_cache_set(lua_State *L) {
int args = lua_gettop(L);
int args = lua_gettop(L);
const char *key ;
const char *value ;
uint64_t expires = 0;
size_t vallen;
size_t vallen;
if (!uwsgi.cache_max_items) goto error;
if (args > 1) {
if (args > 1) {
key = lua_tolstring(L, 1, NULL);
value = lua_tolstring(L, 2, &vallen);
if (args > 2) {
expires = lua_tonumber(L, 3);
}
key = lua_tolstring(L, 1, NULL);
value = lua_tolstring(L, 2, &vallen);
if (args > 2) {
expires = lua_tonumber(L, 3);
}
uwsgi_cache_set((char *)key, strlen(key), (char *)value, (uint16_t) vallen, expires, 0);
}
uwsgi_wlock(uwsgi.cache_lock);
uwsgi_cache_set((char *)key, strlen(key), (char *)value, (uint16_t) vallen, expires, 0);
uwsgi_rwunlock(uwsgi.cache_lock);
}
lua_pushnil(L);
return 1;
error:
lua_pushnil(L);
return 1;
}
static int uwsgi_api_cache_update(lua_State *L) {
int args = lua_gettop(L);
const char *key ;
const char *value ;
uint64_t expires = 0;
size_t vallen;
if (!uwsgi.cache_max_items) goto error;
if (args > 1) {
key = lua_tolstring(L, 1, NULL);
value = lua_tolstring(L, 2, &vallen);
if (args > 2) {
expires = lua_tonumber(L, 3);
}
uwsgi_wlock(uwsgi.cache_lock);
uwsgi_cache_set((char *)key, strlen(key), (char *)value,
(uint16_t) vallen, expires,
UWSGI_CACHE_FLAG_UPDATE);
uwsgi_rwunlock(uwsgi.cache_lock);
}
error:
lua_pushnil(L);
return 1;
}
static int uwsgi_api_register_signal(lua_State *L) {
int args = lua_gettop(L);
@@ -184,23 +224,25 @@ static int uwsgi_api_cache_get(lua_State *L) {
char *value ;
uint64_t valsize;
const char *key ;
lca(L, 1);
if (!uwsgi.cache_max_items) goto error;
if (lua_isstring(L, 1)) {
key = lua_tolstring(L, 1, NULL);
uwsgi_rlock(uwsgi.cache_lock);
value = uwsgi_cache_get((char *)key, strlen(key), &valsize);
if (value) {
lua_pushlstring(L, value, valsize);
uwsgi_rwunlock(uwsgi.cache_lock);
return 1;
}
uwsgi_rwunlock(uwsgi.cache_lock);
}
error:
lua_pushnil(L);
return 1;
}
@@ -291,6 +333,57 @@ static int uwsgi_api_req_fd(lua_State *L) {
return 1;
}
static int uwsgi_api_lock(lua_State *L) {
int lock_num = 0;
// the spooler cannot lock resources
#ifdef UWSGI_SPOOLER
if (uwsgi.i_am_a_spooler) {
lua_pushstring(L, "The spooler cannot lock/unlock resources");
lua_error(L);
}
#endif
if (lua_gettop(L) > 0) {
lock_num = lua_isnumber(L, 1) ? lua_tonumber(L, 1) : -1;
if (lock_num < 0 || lock_num > uwsgi.locks) {
lua_pushstring(L, "Invalid lock number");
lua_error(L);
}
}
uwsgi_lock(uwsgi.user_lock[lock_num]);
return 0;
}
static int uwsgi_api_unlock(lua_State *L) {
int lock_num = 0;
// the spooler cannot lock resources
#ifdef UWSGI_SPOOLER
if (uwsgi.i_am_a_spooler) {
lua_pushstring(L, "The spooler cannot lock/unlock resources");
lua_error(L);
}
#endif
if (lua_gettop(L) > 0) {
lock_num = lua_isnumber(L, 1) ? lua_tonumber(L, 1) : -1;
if (lock_num < 0 || lock_num > uwsgi.locks) {
lua_pushstring(L, "Invalid lock number");
lua_error(L);
}
}
uwsgi_unlock(uwsgi.user_lock[lock_num]);
return 0;
}
static const luaL_reg uwsgi_api[] = {
{"log", uwsgi_api_log},
{"cl", uwsgi_api_cl},
@@ -298,8 +391,11 @@ static const luaL_reg uwsgi_api[] = {
{"send_message", uwsgi_api_send_message},
{"cache_get", uwsgi_api_cache_get},
{"cache_set", uwsgi_api_cache_set},
{"cache_update", uwsgi_api_cache_update},
{"register_signal", uwsgi_api_register_signal},
{"register_rpc", uwsgi_api_register_rpc},
{"lock", uwsgi_api_lock},
{"unlock", uwsgi_api_unlock},
{NULL, NULL}
};
-35
View File
@@ -1,35 +0,0 @@
#include "../../uwsgi.h"
struct uwsgi_mono {
char *assembly_name ;
} um;
int uwsgi_mono_init() {
MonoDomain *domain;
MonoAssembly *assembly;
MonoImage *image, *corlib;
domain = mono_jit_init("uwsgi");
corlib = mono_get_corlib();
if (!corlib) {
uwsgi_log("unable to initialize MONO engine\n");
exit(1);
}
image = mono_assembly_get_image(assembly);
}
struct uwsgi_plugin mono_plugin = {
.name = "mono",
.init = uwsgi_mono_init,
};
+10 -3
View File
@@ -26,6 +26,7 @@ struct uwsgi_php {
char *docroot;
char *app;
char *app_qs;
char *fallback;
size_t ini_size;
int dump_config;
char *server_software;
@@ -53,6 +54,7 @@ struct uwsgi_option uwsgi_php_options[] = {
{"php-app", required_argument, 0, "force the php file to run at each request", uwsgi_opt_set_str, &uphp.app, 0},
{"php-var", required_argument, 0, "add/overwrite a CGI variable at each request", uwsgi_opt_add_string_list, &uphp.vars, 0},
{"php-app-qs", required_argument, 0, "when in app mode force QUERY_STRING to the specified value + PATH_INFO", uwsgi_opt_set_str, &uphp.app_qs, 0},
{"php-fallback", required_argument, 0, "run the specified php script when the request one does not exist", uwsgi_opt_set_str, &uphp.fallback, 0},
{"php-dump-config", no_argument, 0, "dump php config (if modified via --php-set or append options)", uwsgi_opt_true, &uphp.dump_config, 0},
{0, 0, 0, 0, 0, 0, 0},
@@ -717,7 +719,6 @@ int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
*(dst+part_size-1) = 0;
if (stat(full_path, &st)) {
uwsgi_php_404(wsgi_req);
return -1;
}
@@ -727,7 +728,6 @@ int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot
if (i < (wsgi_req->path_info_len)-1) {
*path_info = ptr + i;
}
return 0;
}
@@ -823,9 +823,16 @@ appready:
if (uwsgi_php_walk(wsgi_req, filename, wsgi_req->document_root, wsgi_req->document_root_len, &path_info)) {
free(filename);
return -1;
if (uphp.fallback) {
filename = uwsgi_str(uphp.fallback);
}
else {
uwsgi_php_404(wsgi_req);
return -1;
}
}
char *orig_path_info = wsgi_req->path_info;
uint16_t orig_path_info_len = wsgi_req->path_info_len;
+7
View File
@@ -23,6 +23,9 @@ struct uwsgi_perl {
int no_die_catch;
int stacktrace_available;
char *argv_items;
struct uwsgi_string_list *argv_item;
// this is a pointer to the main list of interpreters (required for signals, rpc....);
PerlInterpreter **main;
@@ -37,6 +40,9 @@ struct uwsgi_perl {
CV **tmp_psgix_logger;
CV **tmp_stream_responder;
SV *postfork;
SV *atexit;
};
void init_perl_embedded_module(void);
@@ -52,3 +58,4 @@ int uwsgi_perl_obj_isa(SV *, char *);
int init_psgi_app(struct wsgi_request *, char *, uint16_t, PerlInterpreter **);
PerlInterpreter *uwsgi_perl_new_interpreter(void);
int uwsgi_perl_mule(char *);
void uwsgi_perl_run_hook(SV *);
+35 -3
View File
@@ -21,7 +21,12 @@ XS(XS_error) {
psgi_check_args(0);
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[wsgi_req->async_id]);
if (uwsgi.threads > 1) {
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[wsgi_req->async_id]);
}
else {
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[0]);
}
XSRETURN(1);
}
@@ -32,7 +37,12 @@ XS(XS_input) {
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
psgi_check_args(0);
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[wsgi_req->async_id]);
if (uwsgi.threads > 1) {
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[wsgi_req->async_id]);
}
else {
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[0]);
}
XSRETURN(1);
}
@@ -66,7 +76,12 @@ XS(XS_stream)
while (psgi_response(wsgi_req, response) != UWSGI_OK);
SvREFCNT_dec(response);
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[wsgi_req->async_id]);
if (uwsgi.threads > 1) {
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[wsgi_req->async_id]);
}
else {
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[0]);
}
XSRETURN(1);
}
else {
@@ -413,6 +428,23 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
}
}
if (uperl.argv_items || uperl.argv_item) {
AV *uperl_argv = GvAV(PL_argvgv);
if (uperl.argv_items) {
char *argv_list = uwsgi_str(uperl.argv_items);
char *p = strtok(argv_list, " ");
while(p) {
av_push(uperl_argv, newSVpv(p, 0));
p = strtok(NULL, " ");
}
}
struct uwsgi_string_list *usl = uperl.argv_item;
while(usl) {
av_push(uperl_argv, newSVpv(usl->value, usl->len));
usl = usl->next;
}
}
SV *dollar_zero = get_sv("0", GV_ADD);
sv_setsv(dollar_zero, newSVpv(app, app_len));
+92 -7
View File
@@ -16,6 +16,11 @@ struct uwsgi_option uwsgi_perl_options[] = {
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
{"perl-no-die-catch", no_argument, 0, "do not catch $SIG{__DIE__}", uwsgi_opt_true, &uperl.no_die_catch, 0},
{"perl-local-lib", required_argument, 0, "set perl locallib path", uwsgi_opt_set_str, &uperl.locallib, 0},
#ifdef PERL_VERSION_STRING
{"perl-version", no_argument, 0, "print perl version", uwsgi_opt_print, PERL_VERSION_STRING, UWSGI_OPT_IMMEDIATE},
#endif
{"perl-args", required_argument, 0, "add items (space separated) to @ARGV", uwsgi_opt_set_str, &uperl.argv_items, 0},
{"perl-arg", required_argument, 0, "add an item to @ARGV", uwsgi_opt_add_string_list, &uperl.argv_item, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -57,7 +62,12 @@ SV *uwsgi_perl_call_stream(SV *func) {
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( sv_2mortal(newRV((SV*) ((SV **)wi->responder0)[wsgi_req->async_id])));
if (uwsgi.threads > 1) {
XPUSHs( sv_2mortal(newRV((SV*) ((SV **)wi->responder0)[wsgi_req->async_id])));
}
else {
XPUSHs( sv_2mortal(newRV((SV*) ((SV **)wi->responder0)[0])));
}
PUTBACK;
call_sv( func, G_SCALAR | G_EVAL);
@@ -291,7 +301,12 @@ SV *build_psgi_env(struct wsgi_request *wsgi_req) {
if (!hv_store(env, "psgix.input.buffered", 20, newSViv(wsgi_req->body_as_file), 0)) goto clear;
if (!hv_store(env, "psgix.logger", 12,newRV((SV*) ((SV **)wi->responder1)[wsgi_req->async_id]) ,0)) goto clear;
if (uwsgi.threads > 1) {
if (!hv_store(env, "psgix.logger", 12,newRV((SV*) ((SV **)wi->responder1)[wsgi_req->async_id]) ,0)) goto clear;
}
else {
if (!hv_store(env, "psgix.logger", 12,newRV((SV*) ((SV **)wi->responder1)[0]) ,0)) goto clear;
}
if (uwsgi.master_process) {
if (!hv_store(env, "psgix.harakiri", 14, newSViv(1), 0)) goto clear;
@@ -426,8 +441,15 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
wi->requests++;
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
PERL_SET_CONTEXT(((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id]);
if (uwsgi.threads < 2) {
if (((PerlInterpreter **)wi->interpreter)[0] != uperl.main[0]) {
PERL_SET_CONTEXT(((PerlInterpreter **)wi->interpreter)[0]);
}
}
else {
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
PERL_SET_CONTEXT(((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id]);
}
}
ENTER;
@@ -436,7 +458,12 @@ int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
wsgi_req->async_environ = build_psgi_env(wsgi_req);
if (!wsgi_req->async_environ) goto clear;
wsgi_req->async_result = psgi_call(wsgi_req, ((SV **)wi->callable)[wsgi_req->async_id], wsgi_req->async_environ);
if (uwsgi.threads > 1) {
wsgi_req->async_result = psgi_call(wsgi_req, ((SV **)wi->callable)[wsgi_req->async_id], wsgi_req->async_environ);
}
else {
wsgi_req->async_result = psgi_call(wsgi_req, ((SV **)wi->callable)[0], wsgi_req->async_environ);
}
if (!wsgi_req->async_result) goto clear;
if (SvTYPE((AV *)wsgi_req->async_result) == SVt_PVCV) {
@@ -469,8 +496,15 @@ clear:
LEAVE;
// restore main interpreter if needed
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
PERL_SET_CONTEXT(uperl.main[wsgi_req->async_id]);
if (uwsgi.threads > 1) {
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
PERL_SET_CONTEXT(uperl.main[wsgi_req->async_id]);
}
}
else {
if (((PerlInterpreter **)wi->interpreter)[0] != uperl.main[0]) {
PERL_SET_CONTEXT(uperl.main[0]);
}
}
return UWSGI_OK;
@@ -554,6 +588,10 @@ void uwsgi_perl_post_fork() {
sv_setiv(GvSV(tmpgv), (IV)getpid());
SvREADONLY_on(GvSV(tmpgv));
}
if (uperl.postfork) {
uwsgi_perl_run_hook(uperl.postfork);
}
}
int uwsgi_perl_mount_app(char *mountpoint, char *app) {
@@ -621,6 +659,51 @@ int uwsgi_perl_signal_handler(uint8_t sig, void *handler) {
return ret;
}
void uwsgi_perl_run_hook(SV *hook) {
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( hook );
PUTBACK;
call_sv( SvRV(hook), G_DISCARD);
if(SvTRUE(ERRSV)) {
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
return;
}
SPAGAIN;
PUTBACK;
FREETMPS;
LEAVE;
}
static void uwsgi_perl_atexit() {
if (uwsgi.mywid == -1) goto realstuff;
// if hijacked do not run atexit hooks
if (uwsgi.workers[uwsgi.mywid].hijacked)
return;
// if busy do not run atexit hooks
if (uwsgi.workers[uwsgi.mywid].busy)
return;
#ifdef UWSGI_ASYNC
// managing atexit in async mode is a real pain...skip it for now
if (uwsgi.async > 1)
return;
#endif
realstuff:
if (uperl.atexit) {
uwsgi_perl_run_hook(uperl.atexit);
}
}
struct uwsgi_plugin psgi_plugin = {
.name = "psgi",
@@ -641,5 +724,7 @@ struct uwsgi_plugin psgi_plugin = {
.after_request = uwsgi_perl_after_request,
.enable_threads = uwsgi_perl_enable_threads,
.atexit = uwsgi_perl_atexit,
.magic = uwsgi_perl_magic,
};
-1
View File
@@ -46,7 +46,6 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
if (SvTRUE(*harakiri)) wsgi_req->async_plagued = 1;
}
SvREFCNT_dec(wsgi_req->async_environ);
SvREFCNT_dec(wsgi_req->async_result);
return UWSGI_OK;
+62
View File
@@ -2,6 +2,7 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_plugin psgi_plugin;
extern struct uwsgi_perl uperl;
#ifdef UWSGI_ASYNC
@@ -171,6 +172,28 @@ XS(XS_register_signal) {
}
XS(XS_postfork) {
dXSARGS;
psgi_check_args(1);
uperl.postfork = newRV_inc(ST(0));
XSRETURN_YES;
}
XS(XS_atexit) {
dXSARGS;
psgi_check_args(1);
uperl.atexit = newRV_inc(ST(0));
XSRETURN_YES;
}
XS(XS_log) {
dXSARGS;
@@ -267,6 +290,41 @@ XS(XS_signal_wait) {
XSRETURN_YES;
}
XS(XS_add_timer) {
dXSARGS;
psgi_check_args(2);
uint8_t uwsgi_signal = SvIV(ST(0));
int seconds = SvIV(ST(1));
if (uwsgi_add_timer(uwsgi_signal, seconds)) {
croak("unable to register timer");
XSRETURN_UNDEF;
}
XSRETURN(1);
}
XS(XS_add_rb_timer) {
dXSARGS;
psgi_check_args(2);
uint8_t uwsgi_signal = SvIV(ST(0));
int seconds = SvIV(ST(1));
if (uwsgi_signal_add_rb_timer(uwsgi_signal, seconds, 0)) {
croak("unable to register rb timer");
XSRETURN_UNDEF;
}
XSRETURN(1);
}
void init_perl_embedded_module() {
psgi_xs(reload);
@@ -282,5 +340,9 @@ void init_perl_embedded_module() {
psgi_xs(signal);
psgi_xs(register_signal);
psgi_xs(signal_wait);
psgi_xs(postfork);
psgi_xs(atexit);
psgi_xs(add_timer);
psgi_xs(add_rb_timer);
}
+20 -3
View File
@@ -46,6 +46,23 @@ void uwsgi_opt_pyrun(char *opt, char *value, void *foobar) {
up.pyrun = value;
}
void uwsgi_opt_pyver(char *opt, char *foo, void *bar) {
#ifndef UWSGI_PYPY
const char *version = Py_GetVersion();
#else
const char *version = PYPY_VERSION;
#endif
const char *space = strchr(version, ' ');
if (space) {
fprintf(stdout, "%.*s\n", (int) (space-version), version);
}
else {
fprintf(stdout, "%s\n", version);
}
exit(0);
}
#ifdef UWSGI_INI
void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
@@ -142,6 +159,8 @@ struct uwsgi_option uwsgi_python_options[] = {
{"wsgi-env-behavior", required_argument, 0, "set the strategy for allocating/deallocating the WSGI env", uwsgi_opt_set_str, &up.wsgi_env_behaviour, 0},
{"start_response-nodelay", no_argument, 0, "send WSGI http headers as soon as possible (PEP violation)", uwsgi_opt_true, &up.start_response_nodelay, 0},
{"python-version", no_argument, 0, "report python version", uwsgi_opt_pyver, NULL, UWSGI_OPT_IMMEDIATE},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -1754,9 +1773,7 @@ int uwsgi_python_mule(char *opt) {
if (uwsgi_endswith(opt, ".py")) {
UWSGI_GET_GIL;
if (uwsgi_pyimport_by_filename("__main__", opt) == NULL) {
return 0;
}
uwsgi_pyimport_by_filename("__main__", opt);
UWSGI_RELEASE_GIL;
return 1;
}
+3 -2
View File
@@ -211,8 +211,9 @@ void init_pyargv() {
#endif
if (*ap != '\0') {
#ifdef PYTHREE
mbstowcs( wcargv + strlen(ap), ap, strlen(ap));
up.py_argv[up.argc] = wcargv + strlen(ap);
mbstowcs( wcargv, ap, strlen(ap));
up.py_argv[up.argc] = wcargv;
wcargv += strlen(ap) + 1;
#else
up.py_argv[up.argc] = ap;
#endif
+4 -2
View File
@@ -419,6 +419,7 @@ PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
return NULL;
}
Py_INCREF(func);
if (uwsgi_register_rpc(name, 0, argc, func)) {
return PyErr_Format(PyExc_ValueError, "unable to register rpc function");
@@ -454,6 +455,8 @@ PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) {
return NULL;
}
Py_INCREF(handler);
if (uwsgi_register_signal(uwsgi_signal, signal_kind, handler, 0)) {
return PyErr_Format(PyExc_ValueError, "unable to register signal");
}
@@ -842,7 +845,7 @@ PyObject *py_uwsgi_advanced_sendfile(PyObject * self, PyObject * args) {
}
#ifdef PYTHREE
else if (PyUnicode_Check(what)) {
filename = PyBytes_AsString(PyUnicode_AsASCIIString(what));
filename = PyBytes_AsString(PyUnicode_AsLatin1String(what));
fd = open(filename, O_RDONLY);
if (fd < 0) {
@@ -2763,7 +2766,6 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
PyDict_SetItemString(worker_dict, "apps", apps_tuple);
Py_DECREF(apps_tuple);
}
+28 -13
View File
@@ -2,9 +2,16 @@ import os,sys
from distutils import sysconfig
def get_python_version():
version = sysconfig.get_config_var('VERSION')
try:
version = version + sys.abiflags
except:
pass
return version
NAME='python'
GCC_LIST = ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter', 'tracebacker']
#OBJ_LIST = ['/usr/lib/libpython2.6.a']
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True) ]
@@ -15,8 +22,26 @@ LDFLAGS = []
if not 'UWSGI_PYTHON_NOLIB' in os.environ:
LIBS = sysconfig.get_config_var('LIBS').split() + sysconfig.get_config_var('SYSLIBS').split()
# check if it is a non-shared build (but please, add --enable-shared to your python's ./configure script)
if not sysconfig.get_config_var('Py_ENABLE_SHARED'):
LIBS.append('-L' + sysconfig.get_config_var('LIBPL'))
libdir = sysconfig.get_config_var('LIBPL')
# libdir does not exists, try to get it from the venv
version = get_python_version()
if not os.path.exists(libdir):
libdir = '%s/lib/python%s/config' % (sys.prefix, version)
# try skipping abiflag
if not os.path.exists(libdir) and version.endswith('m'):
version = version[:-1]
libdir = '%s/lib/python%s/config' % (sys.prefix, version)
# try 3.x style config dir
if not os.path.exists(libdir):
libdir = '%s/lib/python%s/config-%s' % (sys.prefix, version, get_python_version())
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LDLIBRARY'))
if not os.path.exists(libpath):
libpath = '%s/%s' % (libdir, sysconfig.get_config_var('LIBRARY'))
if not os.path.exists(libpath):
libpath = '%s/libpython%s.a' % (libdir, version)
LIBS.append(libpath)
else:
try:
LDFLAGS.append("-L%s" % sysconfig.get_config_var('LIBDIR'))
@@ -25,16 +50,6 @@ if not 'UWSGI_PYTHON_NOLIB' in os.environ:
LDFLAGS.append("-L%s/lib" % sysconfig.PREFIX)
os.environ['LD_RUN_PATH'] = "%s/lib" % sysconfig.PREFIX
version = sysconfig.get_config_var('VERSION')
try:
version = version + sys.abiflags
except:
pass
LIBS.append('-lpython' + version)
LIBS.append('-lpython%s' % get_python_version())
else:
LIBS = []
#if str(PYLIB_PATH) != '':
# libs.insert(0,'-L' + PYLIB_PATH)
# os.environ['LD_RUN_PATH'] = PYLIB_PATH
+6 -3
View File
@@ -180,11 +180,11 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
ssize_t rlen = up.hook_wsgi_input_read(self->wsgi_req, tmp_buf, remains, &tmp_pos);
if (rlen < 0) {
free(tmp_buf);
return PyErr_Format(PyExc_IOError, "error reading for wsgi.input data: Content-Length %llu requested %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) (remains + tmp_pos), (unsigned long long) tmp_pos);
return PyErr_Format(PyExc_IOError, "error reading for wsgi.input data: Content-Length %llu requested %llu received %llu pos %llu+%llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) remains, (unsigned long long) tmp_pos, (unsigned long long) self->pos, (unsigned long long) tmp_pos);
}
else if (tmp_pos == 0) {
else if (rlen == 0) {
free(tmp_buf);
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data: Content-Length %llu requested %llu received %llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) (remains + tmp_pos), (unsigned long long) tmp_pos);
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data: Content-Length %llu requested %llu received %llu pos %llu+%llu", (unsigned long long) self->wsgi_req->post_cl, (unsigned long long) remains, (unsigned long long) tmp_pos, (unsigned long long) self->pos, (unsigned long long) tmp_pos);
}
self->pos += tmp_pos;
@@ -588,6 +588,9 @@ PyObject *py_uwsgi_sendfile(PyObject * self, PyObject * args) {
#ifdef PYTHREE
wsgi_req->sendfile_fd = PyObject_AsFileDescriptor(wsgi_req->async_sendfile);
if (wsgi_req->sendfile_fd >= 0) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
}
#else
if (PyFile_Check((PyObject *)wsgi_req->async_sendfile)) {
Py_INCREF((PyObject *)wsgi_req->async_sendfile);
+4 -4
View File
@@ -100,7 +100,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[1].iov_len = 1;
#ifdef PYTHREE
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(head);
PyObject *zero = PyUnicode_AsLatin1String(head);
wsgi_req->hvec[2].iov_base = PyBytes_AsString(zero);
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
Py_DECREF(zero);
@@ -124,7 +124,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[0].iov_len = 8;
#ifdef PYTHREE
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(head);
PyObject *zero = PyUnicode_AsLatin1String(head);
wsgi_req->hvec[1].iov_base = PyBytes_AsString(zero);
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
Py_DECREF(zero);
@@ -198,7 +198,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
#ifdef PYTHREE
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(h_key);
PyObject *zero = PyUnicode_AsLatin1String(h_key);
wsgi_req->hvec[j].iov_base = PyBytes_AsString(zero);
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
Py_DECREF(zero);
@@ -215,7 +215,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[j + 1].iov_len = H_SEP_SIZE;
#ifdef PYTHREE
if (self != Py_None) {
PyObject *zero = PyUnicode_AsASCIIString(h_value);
PyObject *zero = PyUnicode_AsLatin1String(h_value);
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(zero);
PyList_Append((PyObject *) wsgi_req->gc_tracker, zero);
Py_DECREF(zero);
+2
View File
@@ -254,8 +254,10 @@ VALUE rb_uwsgi_io_rewind(VALUE obj, VALUE args) {
}
#ifdef RUBY19
#ifdef RUBY_GLOBAL_SETUP
RUBY_GLOBAL_SETUP
#endif
#endif
VALUE uwsgi_require_file(VALUE arg) {
return rb_funcall(rb_cObject, rb_intern("require"), 1, arg);
+13 -5
View File
@@ -14,7 +14,7 @@ v = version.split('.')
GCC_LIST = ['rack_plugin', 'rack_api']
if v[0] == '1' and v[1] == '9':
if (v[0] == '1' and v[1] == '9') or v[0] >= '2':
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print RbConfig::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-DRUBY19')
CFLAGS.append('-Wno-unused-parameter')
@@ -34,10 +34,18 @@ else:
CFLAGS.append('-I' + archdir + '/' + arch)
CFLAGS.append('-I' + includedir + '/' + arch)
LDFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LDFLAGS']\"" % rbconfig).read().rstrip().split()
libpath = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['libdir']\"" % rbconfig).read().rstrip()
LDFLAGS.append('-L' + libpath )
os.environ['LD_RUN_PATH'] = libpath
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip().split()
has_shared = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['ENABLE_SHARED']\"" % rbconfig).read().rstrip()
LIBS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LIBS']\"" % rbconfig).read().rstrip().split()
if has_shared == 'yes':
LDFLAGS.append('-L' + libpath )
os.environ['LD_RUN_PATH'] = libpath
LIBS.append(os.popen(RUBYPATH + " -e \"require 'rbconfig';print '-l' + %s::CONFIG['RUBY_SO_NAME']\"" % rbconfig).read().rstrip())
else:
GCC_LIST.append("%s/%s" % (libpath, os.popen(RUBYPATH + " -e \"require 'rbconfig';print %s::CONFIG['LIBRUBY_A']\"" % rbconfig).read().rstrip()))
+18 -1
View File
@@ -12,13 +12,24 @@ int uwsgi_routing_func_http(struct wsgi_request *wsgi_req, struct uwsgi_route *u
// get the http address from the route
char *addr = ur->data;
char *uri = NULL;
uint16_t uri_len = 0;
if (ur->data3_len) {
uri = uwsgi_regexp_apply_ovec(wsgi_req->uri, wsgi_req->uri_len, ur->data3, ur->data3_len, ur->ovector, ur->ovn);
uri_len = strlen(uri);
}
// convert the wsgi_request to an http proxy request
struct uwsgi_buffer *ub = uwsgi_to_http(wsgi_req, ur->data2, ur->data2_len);
struct uwsgi_buffer *ub = uwsgi_to_http(wsgi_req, ur->data2, ur->data2_len, uri, uri_len);
if (!ub) {
if (uri) free(uri);
uwsgi_log("unable to generate http request for %s\n", addr);
return UWSGI_ROUTE_NEXT;
}
if (uri) free(uri);
// ok now if have offload threads, directly use them
if (wsgi_req->socket->can_offload) {
if (!uwsgi_offload_request_net_do(wsgi_req, addr, ub)) {
@@ -86,6 +97,12 @@ int uwsgi_router_http(struct uwsgi_route *ur, char *args) {
*comma = 0;
ur->data_len = strlen(ur->data);
ur->data2 = comma+1;
comma = strchr(ur->data2, ',');
if (comma) {
*comma = 0;
ur->data3 = comma+1;
ur->data3_len = strlen(ur->data3);
}
ur->data2_len = strlen(ur->data2);
}
return 0;
+1 -1
View File
@@ -1,6 +1,6 @@
#include "../../uwsgi.h"
void stats_pusher_mongodb(struct uwsgi_stats_pusher_instance *, char *, size_t);
void stats_pusher_mongodb(struct uwsgi_stats_pusher_instance *, time_t, char *, size_t);
static void stats_pusher_mongodb_init(void) {
uwsgi_register_stats_pusher("mongodb", stats_pusher_mongodb);
@@ -12,7 +12,7 @@ struct stats_pusher_mongodb_conf {
};
extern "C" void stats_pusher_mongodb(struct uwsgi_stats_pusher_instance *uspi, char *json, size_t json_len) {
extern "C" void stats_pusher_mongodb(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
struct stats_pusher_mongodb_conf *spmc = (struct stats_pusher_mongodb_conf *) uspi->data;
if (!uspi->configured) {
+28 -5
View File
@@ -270,7 +270,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
char post_buf[8192];
char *post_tail = NULL;
// first round ? this memory area will be freed by async_loop
// first round ?
if (!wsgi_req->proto_parser_buf) {
wsgi_req->proto_parser_buf = uwsgi_malloc(uwsgi.buffer_size);
}
@@ -281,12 +281,15 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
remains = UMIN(remains, 8192);
len = read(wsgi_req->poll.fd, post_buf, remains);
if (len <= 0) {
if (len < 0)
if (len < 0) {
free(wsgi_req->proto_parser_buf);
uwsgi_error("read()");
}
return -1;
}
if (!fwrite(post_buf, len, 1, wsgi_req->async_post)) {
free(wsgi_req->proto_parser_buf);
uwsgi_error("fwrite()");
return -1;
}
@@ -296,6 +299,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
return UWSGI_AGAIN;
}
free(wsgi_req->proto_parser_buf);
rewind(wsgi_req->async_post);
wsgi_req->body_as_file = 1;
return UWSGI_OK;
@@ -334,11 +338,14 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
memcpy(post_tail, ptr, remains);
}
http_parse(wsgi_req, ptr);
wsgi_req->uh.modifier1 = uwsgi.http_modifier1;
wsgi_req->uh.modifier2 = uwsgi.http_modifier2;
//is there a Content_Length ?
if (wsgi_req->post_cl > 0) {
wsgi_req->async_post = tmpfile();
if (!wsgi_req->async_post) {
free(wsgi_req->proto_parser_buf);
if (post_tail) free(post_tail);
uwsgi_error("tmpfile()");
return -1;
}
@@ -393,14 +400,19 @@ void uwsgi_httpize_var(char *buf, size_t len) {
}
}
struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req, char *host, uint16_t host_len) {
struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *wsgi_req, char *host, uint16_t host_len, char *uri, uint16_t uri_len) {
struct uwsgi_buffer *ub = uwsgi_buffer_new(4096);
if (uwsgi_buffer_append(ub, wsgi_req->method, wsgi_req->method_len)) goto clear;
if (uwsgi_buffer_append(ub, " ", 1)) goto clear;
if (uwsgi_buffer_append(ub, wsgi_req->uri, wsgi_req->uri_len)) goto clear;
if (uri_len && uri) {
if (uwsgi_buffer_append(ub, uri, uri_len)) goto clear;
}
else {
if (uwsgi_buffer_append(ub, wsgi_req->uri, wsgi_req->uri_len)) goto clear;
}
if (uwsgi_buffer_append(ub, " HTTP/1.0\r\n", 11)) goto clear;
@@ -447,11 +459,22 @@ next:
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
}
if (wsgi_req->content_type_len > 0) {
if (uwsgi_buffer_append(ub, "Content-Type: ", 14)) goto clear;
if (uwsgi_buffer_append(ub, wsgi_req->content_type, wsgi_req->content_type_len)) goto clear;
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
}
if (wsgi_req->post_cl > 0) {
if (uwsgi_buffer_append(ub, "Content-Length: ", 16)) goto clear;
if (uwsgi_buffer_num64(ub, (int64_t) wsgi_req->post_cl)) goto clear;
if (uwsgi_buffer_append(ub, "\r\n", 2)) goto clear;
}
// append required headers
if (uwsgi_buffer_append(ub, "Connection: close\r\n", 19)) goto clear;
if (uwsgi_buffer_append(ub, "X-Forwarded-For: ", 17)) goto clear;
if (x_forwarded_for_len > 0) {
if (uwsgi_buffer_append(ub, x_forwarded_for, x_forwarded_for_len)) goto clear;
if (uwsgi_buffer_append(ub, ", ", 2)) goto clear;
+8
View File
@@ -33,6 +33,14 @@ my $three = sub {
print "three\n";
};
uwsgi::postfork(sub {
print "forked !!!\n";
});
uwsgi::atexit(sub {
print "exited\n";
});
my $app = sub {
my $env = shift;
uwsgi::signal(17);
+1 -1
View File
@@ -3,7 +3,7 @@ import uwsgi
sleepvalue = 5
def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/html')])
start_response('200 Ok', [('Content-type', 'text/html')])
yield uwsgi.async_sleep(sleepvalue)
#print "TIMEOUT: ", env['x-wsgiorg.fdevent.timeout']
yield "<h1>Hello World after %d seconds</h1>" % sleepvalue
+15
View File
@@ -0,0 +1,15 @@
Gem::Specification.new do |s|
s.name = 'uwsgi'
s.license = 'GPL-2'
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
s.date = '2013-03-02'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
s.email = 'info@unbit.it'
s.extensions = ['ext/uwsgi/extconf.rb']
s.files = []
s.require_paths = ['.']
s.executables << 'uwsgi'
s.homepage = 'http://projects.unbit.it/uwsgi'
end
+75 -79
View File
@@ -34,8 +34,23 @@ extern "C" {
#define wsgi_req_time ((wsgi_req->end_of_request-wsgi_req->start_of_request)/1000)
#define thunder_lock if (uwsgi.threads > 1 && !uwsgi.is_et) {pthread_mutex_lock(&uwsgi.thunder_mutex);}
#define thunder_unlock if (uwsgi.threads > 1 && !uwsgi.is_et) {pthread_mutex_unlock(&uwsgi.thunder_mutex);}
#define thunder_lock if (!uwsgi.is_et) {\
if (uwsgi.use_thunder_lock) {\
uwsgi_lock(uwsgi.the_thunder_lock);\
}\
else if (uwsgi.threads > 1) {\
pthread_mutex_lock(&uwsgi.thunder_mutex);\
}\
}
#define thunder_unlock if (!uwsgi.is_et) {\
if (uwsgi.use_thunder_lock) {\
uwsgi_unlock(uwsgi.the_thunder_lock);\
}\
else if (uwsgi.threads > 1) {\
pthread_mutex_unlock(&uwsgi.thunder_mutex);\
}\
}
#define uwsgi_check_scheme(file) (!uwsgi_startswith(file, "emperor://", 10) || !uwsgi_startswith(file, "http://", 7) || !uwsgi_startswith(file, "data://", 7) || !uwsgi_startswith(file, "sym://", 6) || !uwsgi_startswith(file, "fd://", 5) || !uwsgi_startswith(file, "exec://", 7) || !uwsgi_startswith(file, "section://", 10))
@@ -295,6 +310,8 @@ extern int pivot_root(const char *new_root, const char *put_old);
#include <openssl/err.h>
#endif
#include <glob.h>
struct uwsgi_buffer {
char *buf;
@@ -309,6 +326,7 @@ struct uwsgi_string_list {
size_t len;
uint64_t custom;
uint64_t custom2;
void *custom_ptr;
struct uwsgi_string_list *next;
};
@@ -394,6 +412,25 @@ struct uwsgi_regexp_list {
};
#endif
struct uwsgi_rbtree {
struct uwsgi_rb_timer *root;
struct uwsgi_rb_timer *sentinel;
};
struct uwsgi_rb_timer {
uint8_t color;
struct uwsgi_rb_timer *parent;
struct uwsgi_rb_timer *left;
struct uwsgi_rb_timer *right;
uint64_t value;
void *data;
};
struct uwsgi_rbtree *uwsgi_init_rb_timer(void);
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct uwsgi_rbtree *, struct uwsgi_rb_timer *);
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct uwsgi_rbtree *, uint64_t, void *);
void uwsgi_del_rb_timer(struct uwsgi_rbtree *, struct uwsgi_rb_timer *);
union uwsgi_sockaddr {
struct sockaddr sa;
@@ -850,6 +887,9 @@ struct uwsgi_route {
void *data2;
size_t data2_len;
void *data3;
size_t data3_len;
// 64bit value for custom usage
uint64_t custom;
@@ -905,6 +945,7 @@ struct uwsgi_alarm_ll {
struct uwsgi_alarm_log {
pcre *pattern;
pcre_extra *pattern_extra;
int negate;
struct uwsgi_alarm_ll *alarms;
struct uwsgi_alarm_log *next;
};
@@ -991,6 +1032,12 @@ struct wsgi_request {
char *authorization;
uint16_t authorization_len;
char *user_agent;
uint16_t user_agent_len;
char *referer;
uint16_t referer_len;
char *script;
uint16_t script_len;
char *module;
@@ -1262,6 +1309,9 @@ struct uwsgi_server {
int reuse_port;
uint64_t http_modifier1;
uint64_t http_modifier2;
// enable lazy mode
int lazy;
// enable lazy-apps mode
@@ -1289,6 +1339,7 @@ struct uwsgi_server {
// true if run under the emperor
int has_emperor;
char *emperor_procname;
int emperor_fd;
int emperor_queue;
int emperor_tyrant;
@@ -1308,6 +1359,7 @@ struct uwsgi_server {
pid_t emperor_pid;
int emperor_broodlord;
int emperor_broodlord_count;
uint64_t emperor_broodlord_num;
char *emperor_stats;
int emperor_stats_fd;
struct uwsgi_string_list *vassals_templates;
@@ -1546,7 +1598,7 @@ struct uwsgi_server {
struct uwsgi_async_request *async_runqueue_last;
int async_runqueue_cnt;
struct rb_root *rb_async_timeouts;
struct uwsgi_rbtree *rb_async_timeouts;
int async_queue_unused_ptr;
struct wsgi_request **async_queue_unused;
@@ -1670,9 +1722,12 @@ struct uwsgi_server {
#ifdef UWSGI_THREADING
// avoid thundering herd in threaded modes
pthread_mutex_t thunder_mutex;
pthread_mutex_t six_feet_under_lock;
pthread_mutex_t lock_static;
#endif
int use_thunder_lock;
struct uwsgi_lock_item *the_thunder_lock;
/* the list of workers */
@@ -1684,6 +1739,7 @@ struct uwsgi_server {
struct uwsgi_mule *mules;
struct uwsgi_string_list *farms_list;
struct uwsgi_farm *farms;
int mule_msg_size;
pid_t mypid;
int mywid;
@@ -1856,8 +1912,6 @@ struct uwsgi_server {
size_t queue_filesize;
int queue_store_sync;
pthread_mutex_t thunder_mutex;
int locks;
struct uwsgi_lock_item *cache_lock;
@@ -2587,74 +2641,6 @@ struct uwsgi_subscribe_req {
uint16_t base_len;
};
#ifndef _NO_UWSGI_RB
/*
*** uWSGI, stripped down version of Linux rbtree ***
Red Black Trees
(C) 1999 Andrea Arcangeli <andrea@suse.de>
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 St, Fifth Floor, Boston, MA 02110-1301 USA
*/
struct rb_node
{
unsigned long rb_parent_color;
#define RB_RED 0
#define RB_BLACK 1
struct rb_node *rb_right;
struct rb_node *rb_left;
} __attribute__((aligned(sizeof(long))));
/* The alignment might seem pointless, but allegedly CRIS needs it */
struct rb_root
{
struct rb_node *rb_node;
};
#define rb_parent(r) ((struct rb_node *)((r)->rb_parent_color & ~3))
#define rb_color(r) ((r)->rb_parent_color & 1)
#define rb_is_red(r) (!rb_color(r))
#define rb_is_black(r) rb_color(r)
#define rb_set_red(r) do { (r)->rb_parent_color &= ~1; } while (0)
#define rb_set_black(r) do { (r)->rb_parent_color |= 1; } while (0)
void rb_insert_color(struct rb_node *, struct rb_root *);
void rb_erase(struct rb_node *, struct rb_root *);
void rb_link_node(struct rb_node *, struct rb_node *,
struct rb_node **);
struct uwsgi_rb_timer {
struct rb_node rbt;
time_t key;
void *data;
};
struct rb_root *uwsgi_init_rb_timer(void);
struct uwsgi_rb_timer *uwsgi_add_rb_timer(struct rb_root *, time_t, void *);
struct uwsgi_rb_timer *uwsgi_min_rb_timer(struct rb_root *);
#endif
void uwsgi_nuclear_blast();
void uwsgi_unix_signal(int, void (*)(int));
@@ -2808,7 +2794,7 @@ int uwsgi_get_shared_socket_num(struct uwsgi_socket *);
#ifdef __linux__
void uwsgi_set_cgroup(void);
long uwsgi_num_from_file(char *);
long uwsgi_num_from_file(char *, int);
#endif
void uwsgi_add_sockets_to_queue(int, int);
@@ -2922,6 +2908,7 @@ struct uwsgi_subscribe_slot {
void mule_send_msg(int, char *, size_t);
void create_signal_pipe(int *);
void create_msg_pipe(int *, int);
struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slot **, char *, uint16_t);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node_by_name(struct uwsgi_subscribe_slot **, char *, uint16_t, char *, uint16_t);
struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slot **, char *, uint16_t);
@@ -2993,6 +2980,8 @@ void uwsgi_opt_set_str(char *, char *, void *);
void uwsgi_opt_set_logger(char *, char *, void *);
void uwsgi_opt_set_str_spaced(char *, char *, void *);
void uwsgi_opt_add_string_list(char *, char *, void *);
void uwsgi_opt_add_string_list_custom(char *, char *, void *);
void uwsgi_opt_add_addr_list(char *, char *, void *);
void uwsgi_opt_add_dyn_dict(char *, char *, void *);
#ifdef UWSGI_PCRE
void uwsgi_opt_pcre_jit(char *, char *, void *);
@@ -3073,6 +3062,7 @@ void uwsgi_opt_noop(char *, char *, void *);
void uwsgi_opt_logic(char *, char *, void *);
int uwsgi_logic_opt_for(char *, char *);
int uwsgi_logic_opt_for_glob(char *, char *);
int uwsgi_logic_opt_if_env(char *, char *);
int uwsgi_logic_opt_if_not_env(char *, char *);
int uwsgi_logic_opt_if_opt(char *, char *);
@@ -3168,7 +3158,7 @@ struct uwsgi_stats_pusher_instance;
struct uwsgi_stats_pusher {
char *name;
void (*func)(struct uwsgi_stats_pusher_instance *, char *, size_t);
void (*func)(struct uwsgi_stats_pusher_instance *, time_t, char *, size_t);
struct uwsgi_stats_pusher *next;
};
@@ -3176,6 +3166,7 @@ struct uwsgi_stats_pusher_instance {
struct uwsgi_stats_pusher *pusher;
char *arg;
void *data;
int raw;
int configured;
int freq;
time_t last_run;
@@ -3184,13 +3175,14 @@ struct uwsgi_stats_pusher_instance {
struct uwsgi_thread;
void uwsgi_stats_pusher_loop(struct uwsgi_thread *);
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *, char *, size_t);
void uwsgi_stats_pusher_socket(struct uwsgi_stats_pusher_instance *, char *, size_t);
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *, time_t, char *, size_t);
void uwsgi_stats_pusher_socket(struct uwsgi_stats_pusher_instance *, time_t, char *, size_t);
void uwsgi_stats_pusher_setup(void);
void uwsgi_send_stats(int, struct uwsgi_stats * (*func)(void));
struct uwsgi_stats *uwsgi_master_generate_stats(void);
void uwsgi_register_stats_pusher(char *, void(*) (struct uwsgi_stats_pusher_instance *, char *, size_t));
struct uwsgi_stats_pusher *uwsgi_register_stats_pusher(char *, void(*) (struct uwsgi_stats_pusher_instance *, time_t, char *, size_t));
struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *, char *);
struct uwsgi_stats *uwsgi_stats_new(size_t);
int uwsgi_stats_symbol(struct uwsgi_stats *, char);
@@ -3216,6 +3208,7 @@ void manage_cluster_message(char *, int);
void uwsgi_opt_add_custom_option(char *, char *, void *);
void uwsgi_opt_cflags(char *, char *, void *);
void uwsgi_opt_connect_and_read(char *, char *, void *);
void uwsgi_opt_extract(char *, char *, void *);
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *, char *, size_t);
@@ -3363,9 +3356,10 @@ int uwsgi_buffer_append(struct uwsgi_buffer *, char *, size_t);
int uwsgi_buffer_fix(struct uwsgi_buffer *, size_t);
int uwsgi_buffer_ensure(struct uwsgi_buffer *, size_t);
void uwsgi_buffer_destroy(struct uwsgi_buffer *);
int uwsgi_buffer_num64(struct uwsgi_buffer *, int64_t);
void uwsgi_httpize_var(char *, size_t);
struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *, char *, uint16_t);
struct uwsgi_buffer *uwsgi_to_http(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
ssize_t uwsgi_pipe(int, int, int);
ssize_t uwsgi_pipe_sized(int, int, size_t, int);
@@ -3482,6 +3476,8 @@ void simple_loop_run_int(int);
int uwsgi_valid_fd(int);
void uwsgi_close_all_fds(void);
int uwsgi_write_nb(int, char *, size_t, int);
void uwsgi_check_emperor(void);
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
+8 -4
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.4.3'
uwsgi_version = '1.4.10'
import os
import re
@@ -345,12 +345,16 @@ def build_uwsgi(uc, print_only=False):
pass
for cfile in up.GCC_LIST:
if not cfile.endswith('.a'):
if cfile.endswith('.a'):
gcc_list.append(cfile)
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m'):
compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts,
path + '/' + cfile + '.o', path + '/' + cfile + '.c')
gcc_list.append('%s/%s' % (path, cfile))
else:
gcc_list.append(cfile)
compile(' '.join(uniq_warnings(p_cflags)), last_cflags_ts,
path + '/' + cfile + '.o', path + '/' + cfile)
gcc_list.append('%s/%s' % (path, cfile))
libs += up.LIBS
@@ -453,7 +457,7 @@ class uConf(object):
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer',
'core/plugins', 'core/lock', 'core/cache', 'core/daemons',
'core/queue', 'core/event', 'core/signal', 'core/cluster',
'core/rpc', 'core/gateway', 'core/loop', 'lib/rbtree', 'core/rb_timers', 'core/uwsgi']
'core/rpc', 'core/gateway', 'core/loop', 'core/rb_timers', 'core/uwsgi']
# add protocols
self.gcc_list.append('proto/base')
self.gcc_list.append('proto/uwsgi')
+13 -2
View File
@@ -1,4 +1,5 @@
import uwsgi
import sys
from threading import Thread
try:
@@ -170,7 +171,12 @@ class mule_brain(object):
def __call__(self):
if uwsgi.mule_id() == self.num:
self.f()
try:
self.f()
except:
exc = sys.exc_info()
sys.excepthook(exc[0], exc[1], exc[2])
sys.exit(1)
class mule_brainloop(mule_brain):
@@ -178,7 +184,12 @@ class mule_brainloop(mule_brain):
def __call__(self):
if uwsgi.mule_id() == self.num:
while True:
self.f()
try:
self.f()
except:
exc = sys.exc_info()
sys.excepthook(exc[0], exc[1], exc[2])
sys.exit(1)
class mule(object):