mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6adbc37a31 | ||
|
|
688d3fff8c | ||
|
|
c0b079deb0 | ||
|
|
9b30c8683b | ||
|
|
9113812b0d | ||
|
|
1abe9f2d12 | ||
|
|
9a37b3653f | ||
|
|
65ad341a31 | ||
|
|
bd31548903 | ||
|
|
dd536cf7ea | ||
|
|
efa27dfc6c | ||
|
|
91b14e0b34 | ||
|
|
74b3d25bcf | ||
|
|
3857e26e4c | ||
|
|
c7d3a27225 | ||
|
|
4f50b4aafc | ||
|
|
d172fb4909 | ||
|
|
c842bb4917 | ||
|
|
d6da6848be | ||
|
|
b1caf56f49 | ||
|
|
00c243bcce | ||
|
|
575dd6beee | ||
|
|
645d021d73 | ||
|
|
0ca320e5fd | ||
|
|
7879a010e8 | ||
|
|
43dd1029ad | ||
|
|
ce7d84b865 | ||
|
|
7ab1795075 | ||
|
|
e1ce4e1011 | ||
|
|
0c02a5104a | ||
|
|
0e244fc59c | ||
|
|
5d6086c84a | ||
|
|
a45be4f7a9 | ||
|
|
dd63bef92e | ||
|
|
621a05d879 | ||
|
|
b857690caf | ||
|
|
edb0a72dfd | ||
|
|
da4af442ad | ||
|
|
04ff580075 | ||
|
|
5925db13cf | ||
|
|
d283fd1aae | ||
|
|
345b22d8f0 | ||
|
|
b8fc89166d | ||
|
|
50ffb9d258 | ||
|
|
9ae1b26d52 | ||
|
|
f281d21a1b | ||
|
|
b9a2b92005 | ||
|
|
92a26d4ff6 | ||
|
|
51360416a7 | ||
|
|
c7bc98a50c | ||
|
|
b4b5c0175a | ||
|
|
7ed3eb36ee | ||
|
|
05c475f597 | ||
|
|
c750dfc1e3 | ||
|
|
01b14f4395 | ||
|
|
46d7d4bf1d | ||
|
|
02d76f12e0 | ||
|
|
719860a349 | ||
|
|
5cce0935fd | ||
|
|
24ef2a838f | ||
|
|
8aa739b4b2 | ||
|
|
9221e1953e | ||
|
|
18592fb2bd | ||
|
|
fc80eeb581 | ||
|
|
bc19b58681 | ||
|
|
8f2202eab5 | ||
|
|
aa2ecf14df | ||
|
|
43f5792826 | ||
|
|
36ff37e12c | ||
|
|
6dd6f961e8 | ||
|
|
5dd5d92ffb | ||
|
|
64f1b844bd | ||
|
|
e562c4691d | ||
|
|
1cbab74f0e | ||
|
|
3053fdb25a | ||
|
|
f11f542242 | ||
|
|
32ddf10cfa | ||
|
|
1b54be396c | ||
|
|
f81a4f9736 | ||
|
|
048b339593 | ||
|
|
081a6b90bf | ||
|
|
97f1b6d649 |
@@ -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
|
||||
@@ -1,3 +1,8 @@
|
||||
/*
|
||||
|
||||
apxs2 -i -c mod_proxy_uwsgi.c
|
||||
|
||||
*/
|
||||
#define APR_WANT_MEMFUNC
|
||||
#define APR_WANT_STRFUNC
|
||||
#include "apr_strings.h"
|
||||
@@ -101,6 +106,14 @@ 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");
|
||||
|
||||
@@ -143,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);
|
||||
}
|
||||
@@ -336,8 +349,6 @@ static int uwsgi_handler(request_rec *r, proxy_worker *worker,
|
||||
// ADD PATH_INFO
|
||||
size_t w_len = strlen(worker->name);
|
||||
char *u_path_info = r->filename + 6 + w_len;
|
||||
ap_log_rerror(APLOG_MARK, APLOG_ERR, 0, r,
|
||||
"URL %s: %s %s %s", url, worker->name, r->filename, u_path_info);
|
||||
int delta = 0;
|
||||
if (u_path_info[0] != '/') {
|
||||
delta = 1;
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
#!/usr/bin/env ruby
|
||||
cmd = File.expand_path "#{File.dirname(__FILE__)}/../ext/uwsgi/uwsgi.ruby"
|
||||
|
||||
exec(cmd, *ARGV)
|
||||
+9
-3
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
+4
-8
@@ -105,7 +105,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 +117,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 +145,7 @@ cycle:
|
||||
}
|
||||
}
|
||||
if (uci->djbhash != hash)
|
||||
return 0;
|
||||
continue;
|
||||
if (uci->keysize != keylen)
|
||||
continue;
|
||||
if (!memcmp(uci->key, key, keylen))
|
||||
@@ -188,11 +189,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) {
|
||||
|
||||
+61
-8
@@ -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)) {
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
@@ -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));
|
||||
|
||||
+117
-22
@@ -2032,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;
|
||||
@@ -4109,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++) {
|
||||
@@ -5097,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()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+44
-6
@@ -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);
|
||||
@@ -2888,7 +2906,7 @@ wait_for_call_of_duty:
|
||||
uwsgi_ignition();
|
||||
}
|
||||
// never here
|
||||
pthread_exit(NULL);
|
||||
end_me(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -3317,6 +3335,11 @@ void uwsgi_opt_add_addr_list(char *opt, char *value, void *list) {
|
||||
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) {
|
||||
@@ -3903,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);
|
||||
}
|
||||
|
||||
@@ -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
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
@@ -834,23 +834,7 @@ void uwsgi_corerouter_loop(int id, void *data) {
|
||||
}
|
||||
|
||||
// not having a hook could mean a previous event in the loop cleared it...
|
||||
if (!hook) {
|
||||
// a single event cannot be unexpected..
|
||||
if (nevents == 1) {
|
||||
if (interesting_fd == cr_session->instance_fd) {
|
||||
uwsgi_log("[uwsgi-corerouter] BUG, unexpected event received from backend instance (fd: %d nevents: %d) !!!\n", interesting_fd, nevents);
|
||||
}
|
||||
else if (interesting_fd == cr_session->fd) {
|
||||
uwsgi_log("[uwsgi-corerouter] BUG, unexpected event received from client (fd: %d nevents: %d)!!!\n", interesting_fd, nevents);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-corerouter] BUG, unexpected event received !!!\n");
|
||||
}
|
||||
corerouter_close_session(ucr, cr_session);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!hook) continue;
|
||||
// reset errno (as we use it for internal signalling)
|
||||
errno = 0;
|
||||
ssize_t ret = hook(cr_session);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
@@ -265,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;
|
||||
|
||||
}
|
||||
@@ -293,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;
|
||||
@@ -359,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;
|
||||
@@ -426,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);
|
||||
|
||||
|
||||
+10
-8
@@ -551,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;
|
||||
}
|
||||
@@ -560,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;
|
||||
}
|
||||
@@ -625,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;
|
||||
}
|
||||
@@ -839,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;
|
||||
}
|
||||
@@ -949,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;
|
||||
}
|
||||
@@ -958,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;
|
||||
}
|
||||
@@ -1125,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
|
||||
|
||||
@@ -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);
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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
@@ -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}
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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 *);
|
||||
|
||||
@@ -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));
|
||||
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -842,7 +842,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 +2763,6 @@ PyObject *py_uwsgi_workers(PyObject * self, PyObject * args) {
|
||||
|
||||
|
||||
PyDict_SetItemString(worker_dict, "apps", apps_tuple);
|
||||
Py_DECREF(apps_tuple);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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()))
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+9
-2
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
@@ -395,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;
|
||||
@@ -909,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;
|
||||
};
|
||||
@@ -995,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;
|
||||
@@ -1266,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
|
||||
@@ -1293,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;
|
||||
@@ -1312,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;
|
||||
@@ -1550,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;
|
||||
@@ -1674,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 */
|
||||
@@ -1688,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;
|
||||
@@ -1860,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;
|
||||
@@ -2591,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));
|
||||
@@ -2926,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);
|
||||
@@ -2997,6 +2980,7 @@ 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
|
||||
@@ -3078,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 *);
|
||||
@@ -3173,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;
|
||||
};
|
||||
|
||||
@@ -3181,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;
|
||||
@@ -3189,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);
|
||||
@@ -3221,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);
|
||||
|
||||
@@ -3488,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 **);
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.4.4'
|
||||
uwsgi_version = '1.4.10'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -457,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
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user