mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ed368d0d51 | ||
|
|
21f21d34ba | ||
|
|
f37823c809 | ||
|
|
6eaefcff5e | ||
|
|
79235c1cc3 | ||
|
|
29135f014b | ||
|
|
13c998fb8d | ||
|
|
71bfd0d636 | ||
|
|
51e99e0f5a | ||
|
|
66e7beefc4 | ||
|
|
f2b10c35b7 | ||
|
|
e951eba96c | ||
|
|
9fe18da7a3 | ||
|
|
a14fdead14 | ||
|
|
9a671a4991 | ||
|
|
8f5e7b124a | ||
|
|
5f7464d015 | ||
|
|
238dd6c1d0 | ||
|
|
82e4e54edc | ||
|
|
9946cbb9da | ||
|
|
2474adb23a | ||
|
|
f40757bb67 | ||
|
|
bc29479930 | ||
|
|
4ec78edaa3 | ||
|
|
aa0271158d | ||
|
|
c0aa5bfe17 | ||
|
|
3f8e6a8cc8 | ||
|
|
ef0316fc2e | ||
|
|
7274efab15 | ||
|
|
e44b62b6b2 | ||
|
|
31c041d435 | ||
|
|
35f47371ed | ||
|
|
c5412e1620 | ||
|
|
a9b4c52811 | ||
|
|
5ce40b6ac8 | ||
|
|
b93dcbf46f | ||
|
|
8051a2bc98 | ||
|
|
78d8b221fc | ||
|
|
d51cada284 | ||
|
|
389eef9e88 | ||
|
|
270fb0c50d | ||
|
|
e7e9dfee88 | ||
|
|
3bafae276d | ||
|
|
cfebe2927d | ||
|
|
1d4294a845 | ||
|
|
12cfdd9864 | ||
|
|
add930c517 | ||
|
|
32972978be | ||
|
|
c8bad3550e | ||
|
|
ecc55d789d | ||
|
|
88555e2c20 | ||
|
|
ec2bfcd302 | ||
|
|
f1f81ed4c4 | ||
|
|
87933cca26 | ||
|
|
2dcd8624a2 | ||
|
|
7fcef76bbe | ||
|
|
2a5c4e938d | ||
|
|
274eae27ef | ||
|
|
207220bc50 | ||
|
|
fb8c4439c7 | ||
|
|
894be9c41e | ||
|
|
0a4bff8963 | ||
|
|
d515f3e279 | ||
|
|
e8aa0e1e26 | ||
|
|
46a8aae908 | ||
|
|
a9f90464e6 | ||
|
|
4bcdba2334 | ||
|
|
64a8f3464a | ||
|
|
e640bd6f9b | ||
|
|
71a6726bcf | ||
|
|
fe13774b4b | ||
|
|
ecc3a5e8e2 | ||
|
|
dd1881576a | ||
|
|
322a2d2365 | ||
|
|
a76d7a1c66 | ||
|
|
5631dcabf8 | ||
|
|
3f731e2577 | ||
|
|
7a1b7f299b | ||
|
|
322673215e | ||
|
|
b58a0c4969 | ||
|
|
c5fe8c6d30 | ||
|
|
7f54f5075d | ||
|
|
95d4cea3bb | ||
|
|
d6ff3ac018 | ||
|
|
1f4099c874 | ||
|
|
8cd298de34 | ||
|
|
851df33977 | ||
|
|
17f3f3d9a0 | ||
|
|
4273489e42 | ||
|
|
57077ac68c | ||
|
|
45f61435a1 | ||
|
|
28153af4ad | ||
|
|
341cfd90b6 | ||
|
|
82342577a4 | ||
|
|
9d735fdbea | ||
|
|
1775526b89 | ||
|
|
c84f205c74 | ||
|
|
591faabc00 | ||
|
|
e945003d07 | ||
|
|
26c6ec4283 |
@@ -1,5 +1,9 @@
|
||||
*.o
|
||||
*.py[co]
|
||||
*.class
|
||||
*.jar
|
||||
|
||||
/uwsgi
|
||||
/uwsgibuild.*
|
||||
|
||||
/t/ring/target
|
||||
|
||||
@@ -1,683 +0,0 @@
|
||||
*** current ***
|
||||
|
||||
* 1.5
|
||||
|
||||
- added --not-alarm-log
|
||||
- support for TCP_FASTOPEN (Linux-only)
|
||||
- improved emperor reloading
|
||||
- added --get
|
||||
- Legion subsystem
|
||||
- emperor_zeromq plugin
|
||||
- SNI support
|
||||
- distributed SSL session cache
|
||||
|
||||
*** 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 +0,0 @@
|
||||
object file for embedded files will be put here
|
||||
@@ -1,18 +1,13 @@
|
||||
[uwsgi]
|
||||
xml = auto
|
||||
ini = true
|
||||
yaml = true
|
||||
json = auto
|
||||
sqlite3 = auto
|
||||
zeromq = auto
|
||||
snmp = true
|
||||
ssl = auto
|
||||
async = true
|
||||
ldap = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
alarm = auto
|
||||
ipv6 = false
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
[uwsgi]
|
||||
# pypy,jvm,ring,jwsgi
|
||||
main_plugin = erlang,psgi,rack,lua,python,gevent,php,cgi,mono,pyerl,go
|
||||
inherit = base
|
||||
@@ -0,0 +1,34 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
yaml = true
|
||||
json = true
|
||||
sqlite3 = true
|
||||
zeromq = true
|
||||
ssl = true
|
||||
ldap = true
|
||||
pcre = true
|
||||
routing = true
|
||||
debug = false
|
||||
unbit = false
|
||||
xml_implementation = libxml2
|
||||
yaml_implementation = libyaml
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = /usr/lib/libuwsgi.so
|
||||
append_version = ubuntu
|
||||
plugin_dir = /usr/lib/uwsgi
|
||||
embedded_plugins =
|
||||
as_shared_library = true
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
@@ -0,0 +1,6 @@
|
||||
[uwsgi]
|
||||
main_plugin = python,gevent
|
||||
inherit = base
|
||||
plugins = jvm,ring
|
||||
plugin_dir = .
|
||||
|
||||
+13
-5
@@ -1,26 +1,34 @@
|
||||
[uwsgi]
|
||||
xml = true
|
||||
ini = true
|
||||
yaml = true
|
||||
json = false
|
||||
sqlite3 = false
|
||||
zeromq = false
|
||||
ldap = true
|
||||
ssl = true
|
||||
ldap = false
|
||||
pcre = true
|
||||
routing = true
|
||||
alarm = true
|
||||
debug = false
|
||||
unbit = true
|
||||
xml_implementation = expat
|
||||
yaml_implementation = auto
|
||||
malloc_implementation = libc
|
||||
extras =
|
||||
plugins =
|
||||
bin_name = /opt/unbit/bin/uwsgi
|
||||
bin_name = /opt/unbit/uwsgi19/lib/libuwsgi.so
|
||||
append_version = unbit
|
||||
plugin_dir = /opt/unbit/uwsgi_plugins
|
||||
plugin_dir = /opt/unbit/uwsgi19/plugins
|
||||
embedded_plugins =
|
||||
as_shared_library = true
|
||||
|
||||
locking = auto
|
||||
event = auto
|
||||
timer = auto
|
||||
filemonitor = auto
|
||||
|
||||
blacklist =
|
||||
whitelist =
|
||||
|
||||
embed_files =
|
||||
|
||||
embed_config =
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
[uwsgi]
|
||||
inherit = unbit
|
||||
json = false
|
||||
embedded_plugins = python
|
||||
bin_name = ../bin/uwsgi
|
||||
plugin_dir = ../bin/uwsgi_plugins
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
require 'socket'
|
||||
require 'openssl'
|
||||
|
||||
secret = 'ciaociao'
|
||||
iv = ''
|
||||
address = '127.0.0.1'
|
||||
port = 1717
|
||||
algo = 'bf-cbc'
|
||||
|
||||
s = UDPSocket.new
|
||||
s.bind(address, port)
|
||||
cipher = OpenSSL::Cipher.new(algo)
|
||||
cipher.decrypt
|
||||
cipher.key = secret + ("\0" * (cipher.key_len - secret.length))
|
||||
cipher.iv = iv + ("0" * (cipher.iv_len - iv.length))
|
||||
|
||||
loop do
|
||||
msg, sender = s.recvfrom(8192)
|
||||
cipher.reset
|
||||
begin
|
||||
puts cipher.update(msg) + cipher.final
|
||||
rescue
|
||||
end
|
||||
end
|
||||
+218
-51
@@ -135,6 +135,77 @@ int uwsgi_emperor_is_valid(char *name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *emperor_check_on_demand_socket(char *filename) {
|
||||
size_t len = 0;
|
||||
if (uwsgi.emperor_on_demand_extension) {
|
||||
char *tmp = uwsgi_concat2(filename, uwsgi.emperor_on_demand_extension);
|
||||
int fd = open(tmp, O_RDONLY);
|
||||
free(tmp);
|
||||
if (fd < 0) return NULL;
|
||||
char *ret = uwsgi_read_fd(fd, &len, 1);
|
||||
close(fd);
|
||||
// change the first non prinabel character to 0
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (ret[i] < 32) {
|
||||
ret[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret[0] == 0) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
else if (uwsgi.emperor_on_demand_directory) {
|
||||
// we need to build the socket path automagically
|
||||
char *start_of_vassal_name = uwsgi_get_last_char(filename, '/');
|
||||
if (!start_of_vassal_name) {
|
||||
start_of_vassal_name = filename;
|
||||
}
|
||||
else {
|
||||
start_of_vassal_name++;
|
||||
}
|
||||
char *last_dot = uwsgi_get_last_char(filename, '.');
|
||||
if (!last_dot) return NULL;
|
||||
|
||||
return uwsgi_concat4n(uwsgi.emperor_on_demand_directory, strlen(uwsgi.emperor_on_demand_directory), "/", 1, start_of_vassal_name, last_dot - start_of_vassal_name, ".socket", 7);
|
||||
}
|
||||
else if (uwsgi.emperor_on_demand_exec) {
|
||||
int cpipe[2];
|
||||
if (pipe(cpipe)) {
|
||||
uwsgi_error("emperor_check_on_demand_socket()pipe()");
|
||||
return NULL;
|
||||
}
|
||||
char *cmd = uwsgi_concat4(uwsgi.emperor_on_demand_exec, " \"", filename, "\"");
|
||||
int r = uwsgi_run_command(cmd, NULL, cpipe[1]);
|
||||
free(cmd);
|
||||
if (r < 0) {
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
return NULL;
|
||||
}
|
||||
char *ret = uwsgi_read_fd(cpipe[0], &len, 1);
|
||||
close(cpipe[0]);
|
||||
close(cpipe[1]);
|
||||
// change the first non prinabel character to 0
|
||||
size_t i;
|
||||
for(i=0;i<len;i++) {
|
||||
if (ret[i] < 32) {
|
||||
ret[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (ret[0] == 0) {
|
||||
free(ret);
|
||||
return NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// this is the monitor for non-glob directories
|
||||
void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
struct uwsgi_instance *ui_current;
|
||||
@@ -175,7 +246,9 @@ void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
char *socket_name = emperor_check_on_demand_socket(de->d_name);
|
||||
emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, st.st_uid, st.st_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
}
|
||||
closedir(dir);
|
||||
@@ -250,7 +323,9 @@ void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid);
|
||||
char *socket_name = emperor_check_on_demand_socket(g.gl_pathv[i]);
|
||||
emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, st.st_uid, st.st_gid, socket_name);
|
||||
if (socket_name) free(socket_name);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -377,6 +452,22 @@ struct uwsgi_instance *emperor_get_by_fd(int fd) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct uwsgi_instance *emperor_get_by_socket_fd(int fd) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
|
||||
while (c_ui->ui_next) {
|
||||
c_ui = c_ui->ui_next;
|
||||
|
||||
// over engineering...
|
||||
if (c_ui->on_demand_fd != -1 && c_ui->on_demand_fd == fd) {
|
||||
return c_ui;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
||||
struct uwsgi_instance *emperor_get(char *name) {
|
||||
|
||||
@@ -430,6 +521,10 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
uwsgi.emperor_broodlord_count--;
|
||||
}
|
||||
|
||||
if (c_ui->socket_name) {
|
||||
free(c_ui->socket_name);
|
||||
}
|
||||
|
||||
free(c_ui);
|
||||
|
||||
}
|
||||
@@ -478,17 +573,10 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
|
||||
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
|
||||
|
||||
struct uwsgi_instance *c_ui = ui;
|
||||
struct uwsgi_instance *n_ui = NULL;
|
||||
pid_t pid;
|
||||
char **vassal_argv;
|
||||
char *uef;
|
||||
char **uenvs;
|
||||
int counter;
|
||||
char *colon = NULL;
|
||||
int i;
|
||||
struct timeval tv;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -544,8 +632,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
c_ui = c_ui->ui_next;
|
||||
}
|
||||
|
||||
n_ui = uwsgi_malloc(sizeof(struct uwsgi_instance));
|
||||
memset(n_ui, 0, sizeof(struct uwsgi_instance));
|
||||
n_ui = uwsgi_calloc(sizeof(struct uwsgi_instance));
|
||||
|
||||
if (config) {
|
||||
n_ui->use_config = 1;
|
||||
@@ -576,10 +663,60 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
|
||||
n_ui->first_run = uwsgi_now();
|
||||
n_ui->last_run = n_ui->first_run;
|
||||
n_ui->on_demand_fd = -1;
|
||||
if (socket_name) {
|
||||
n_ui->socket_name = uwsgi_str(socket_name);
|
||||
}
|
||||
|
||||
n_ui->pid = -1;
|
||||
|
||||
// ok here we check if we need to bind to the specified socket or continue with the activation
|
||||
if (socket_name) {
|
||||
char *tcp_port = strchr(socket_name, ':');
|
||||
if (tcp_port) {
|
||||
// disable deferred accept for this socket
|
||||
int current_defer_accept = uwsgi.no_defer_accept;
|
||||
uwsgi.no_defer_accept = 1;
|
||||
n_ui->on_demand_fd = bind_to_tcp(socket_name, uwsgi.listen_queue, tcp_port);
|
||||
uwsgi.no_defer_accept = current_defer_accept;
|
||||
}
|
||||
else {
|
||||
n_ui->on_demand_fd = bind_to_unix(socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
}
|
||||
|
||||
if (n_ui->on_demand_fd < 0) {
|
||||
uwsgi_error("emperor_add()/bind()");
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->on_demand_fd);
|
||||
uwsgi_log("[uwsgi-emperor] %s -> \"on demand\" instance detected, waiting for connections on socket \"%s\" ...\n", name, socket_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (uwsgi_emperor_vassal_start(n_ui)) {
|
||||
// clear the vassal
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
|
||||
int i;
|
||||
char *colon = NULL;
|
||||
int counter;
|
||||
char **uenvs;
|
||||
char *uef;
|
||||
char **vassal_argv;
|
||||
pid_t pid;
|
||||
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
|
||||
uwsgi_error("socketpair()");
|
||||
goto clear;
|
||||
return -1;
|
||||
}
|
||||
|
||||
event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]);
|
||||
@@ -587,7 +724,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
if (n_ui->use_config) {
|
||||
if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
|
||||
uwsgi_error("socketpair()");
|
||||
goto clear;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -606,6 +743,11 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
n_ui->pid = pid;
|
||||
// close the right side of the pipe
|
||||
close(n_ui->pipe[1]);
|
||||
// close the "on demand" socket
|
||||
if (n_ui->on_demand_fd > -1) {
|
||||
close(n_ui->on_demand_fd);
|
||||
n_ui->on_demand_fd = -1;
|
||||
}
|
||||
if (n_ui->use_config) {
|
||||
close(n_ui->pipe_config[1]);
|
||||
}
|
||||
@@ -625,13 +767,13 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
|
||||
if (uwsgi.emperor_tyrant) {
|
||||
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
|
||||
if (setgid(gid)) {
|
||||
uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
|
||||
if (setgid(n_ui->gid)) {
|
||||
uwsgi_error("setgid()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -640,7 +782,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (setuid(uid)) {
|
||||
if (setuid(n_ui->uid)) {
|
||||
uwsgi_error("setuid()");
|
||||
exit(1);
|
||||
}
|
||||
@@ -720,7 +862,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
vassal_argv[0] = uwsgi.binary_path;
|
||||
|
||||
if (uwsgi.emperor_broodlord) {
|
||||
colon = strchr(name, ':');
|
||||
colon = strchr(n_ui->name, ':');
|
||||
if (colon) {
|
||||
colon[0] = 0;
|
||||
}
|
||||
@@ -728,17 +870,17 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
// initialize to a default value
|
||||
vassal_argv[1] = "--inherit";
|
||||
|
||||
if (!strcmp(name + (strlen(name) - 4), ".xml"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
|
||||
vassal_argv[1] = "--xml";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".ini"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
|
||||
vassal_argv[1] = "--ini";
|
||||
if (!strcmp(name + (strlen(name) - 4), ".yml"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".yaml"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
|
||||
vassal_argv[1] = "--yaml";
|
||||
if (!strcmp(name + (strlen(name) - 3), ".js"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
|
||||
vassal_argv[1] = "--json";
|
||||
if (!strcmp(name + (strlen(name) - 5), ".json"))
|
||||
if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
|
||||
vassal_argv[1] = "--json";
|
||||
|
||||
if (colon) {
|
||||
@@ -746,16 +888,16 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
}
|
||||
|
||||
|
||||
vassal_argv[2] = name;
|
||||
vassal_argv[2] = n_ui->name;
|
||||
if (uwsgi.emperor_magic_exec) {
|
||||
if (!access(name, R_OK | X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", name);
|
||||
if (!access(n_ui->name, R_OK | X_OK)) {
|
||||
vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
vassal_argv[2] = uwsgi_concat2("emperor://", name);
|
||||
vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
|
||||
}
|
||||
|
||||
counter = 3;
|
||||
@@ -768,18 +910,29 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
}
|
||||
vassal_argv[counter] = NULL;
|
||||
|
||||
// disable stdin
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
// disable stdin OR map it to the "on demand" socket
|
||||
if (n_ui->on_demand_fd > -1) {
|
||||
if (n_ui->on_demand_fd != 0) {
|
||||
if (dup2(n_ui->on_demand_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(n_ui->on_demand_fd);
|
||||
}
|
||||
}
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
else {
|
||||
int stdin_fd = open("/dev/null", O_RDONLY);
|
||||
if (stdin_fd < 0) {
|
||||
uwsgi_error_open("/dev/null");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
if (stdin_fd != 0) {
|
||||
if (dup2(stdin_fd, 0) < 0) {
|
||||
uwsgi_error("dup2()");
|
||||
exit(1);
|
||||
}
|
||||
close(stdin_fd);
|
||||
}
|
||||
}
|
||||
|
||||
// close all of the unneded fd
|
||||
@@ -813,11 +966,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
exit(UWSGI_EXILE_CODE);
|
||||
}
|
||||
|
||||
clear:
|
||||
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void uwsgi_imperial_monitor_glob_init(struct uwsgi_emperor_scanner *ues) {
|
||||
@@ -975,6 +1124,8 @@ void emperor_loop() {
|
||||
char notification_message[64];
|
||||
struct rlimit rl;
|
||||
|
||||
uwsgi.disable_nuclear_blast = 1;
|
||||
|
||||
uwsgi.emperor_stats_fd = -1;
|
||||
|
||||
if (uwsgi.emperor_pidfile) {
|
||||
@@ -1087,14 +1238,24 @@ 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(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid);
|
||||
// here we discard socket name as broodlord/zerg cannot be on demand
|
||||
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
|
||||
free(zerg_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
|
||||
close(interesting_fd);
|
||||
ui_current = emperor_get_by_socket_fd(interesting_fd);
|
||||
if (ui_current) {
|
||||
event_queue_del_fd(uwsgi.emperor_queue, ui_current->on_demand_fd, event_queue_read());
|
||||
if (uwsgi_emperor_vassal_start(ui_current)) {
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
|
||||
close(interesting_fd);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1120,7 +1281,9 @@ void emperor_loop() {
|
||||
has_children = 0;
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
has_children++;
|
||||
if (ui_current->pid > -1) {
|
||||
has_children++;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.notify) {
|
||||
@@ -1172,7 +1335,7 @@ void emperor_loop() {
|
||||
}
|
||||
else {
|
||||
// UNSAFE
|
||||
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid);
|
||||
emperor_add(ui_current->scanner, ui_current->name, ui_current->last_mod, ui_current->config, ui_current->config_len, ui_current->uid, ui_current->gid, ui_current->socket_name);
|
||||
emperor_del(ui_current);
|
||||
}
|
||||
break;
|
||||
@@ -1266,7 +1429,7 @@ void emperor_send_stats(int fd) {
|
||||
if (uwsgi_stats_keyval_comma(us, "id", c_ui->name))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) c_ui->pid))
|
||||
if (uwsgi_stats_keyslong_comma(us, "pid", (long long) c_ui->pid))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "born", (unsigned long long) c_ui->born))
|
||||
goto end0;
|
||||
@@ -1285,6 +1448,9 @@ void emperor_send_stats(int fd) {
|
||||
if (uwsgi_stats_keylong_comma(us, "zerg", (unsigned long long) c_ui->zerg))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keyval_comma(us, "on_demand", c_ui->socket_name ? c_ui->socket_name : ""))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) c_ui->uid))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
|
||||
@@ -1403,6 +1569,7 @@ void uwsgi_emperor_start() {
|
||||
else {
|
||||
uwsgi.emperor_pid = uwsgi_fork("uWSGI Emperor");
|
||||
}
|
||||
|
||||
if (uwsgi.emperor_pid < 0) {
|
||||
uwsgi_error("pid()");
|
||||
exit(1);
|
||||
@@ -1436,7 +1603,7 @@ void uwsgi_check_emperor() {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid) {
|
||||
void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char *config, time_t ts, uid_t uid, gid_t gid, char *socket_name) {
|
||||
|
||||
if (!uwsgi_emperor_is_valid(name))
|
||||
return;
|
||||
@@ -1473,6 +1640,6 @@ void uwsgi_emperor_simple_do(struct uwsgi_emperor_scanner *ues, char *name, char
|
||||
new_config = uwsgi_str(config);
|
||||
new_config_len = strlen(new_config);
|
||||
}
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid);
|
||||
emperor_add(ues, name, ts, new_config, new_config_len, uid, gid, socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
+227
@@ -2,6 +2,233 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
#ifdef UWSGI_EVENT_USE_POLL
|
||||
#define UWSGI_EVENT_IN POLLIN
|
||||
#define UWSGI_EVENT_OUT POLLOUT
|
||||
|
||||
int uwsgi_poll_event_queue_max = 0;
|
||||
struct uwsgi_poll_event {
|
||||
int nevents;
|
||||
int max_events;
|
||||
pthread_mutex_t lock;
|
||||
struct pollfd *poll;
|
||||
};
|
||||
|
||||
struct uwsgi_poll_event **uwsgi_poll_event_queue;
|
||||
|
||||
// all of the public functions must be heavy locked
|
||||
|
||||
static int uwsgi_poll_fd_is_registered(struct uwsgi_poll_event *upe, int fd) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_poll_fd_add(struct uwsgi_poll_event *upe, int fd, int event) {
|
||||
int pos = upe->nevents;
|
||||
if (pos > upe->max_events) return -1;
|
||||
upe->poll[pos].fd = fd;
|
||||
upe->poll[pos].events = event;
|
||||
upe->nevents++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_poll_fd_del(struct uwsgi_poll_event *upe, int fd) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
if (i < upe->nevents-1) {
|
||||
memcpy(&upe->poll[i], &upe->poll[i+1], sizeof(struct uwsgi_poll_event) * (upe->nevents - (i+1)));
|
||||
}
|
||||
upe->nevents--;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_poll_queue_rebuild(struct uwsgi_poll_event *upe) {
|
||||
// we need to check if some file descriptor is no more valid
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (!uwsgi_valid_fd(upe->poll[i].fd)) {
|
||||
uwsgi_poll_fd_del(upe, upe->poll[i].fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int event_queue_wait(int eq, int timeout, int *interesting_fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
uwsgi_poll_queue_rebuild(upe);
|
||||
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].revents) {
|
||||
*interesting_fd = upe->poll[i].fd;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int event_queue_init() {
|
||||
if (!uwsgi_poll_event_queue) {
|
||||
uwsgi_poll_event_queue = uwsgi_calloc(sizeof(struct uwsgi_poll_event *) * uwsgi.max_fd);
|
||||
}
|
||||
int eq = uwsgi_poll_event_queue_max;
|
||||
uwsgi_poll_event_queue[eq] = uwsgi_calloc(sizeof(struct uwsgi_poll_event));
|
||||
uwsgi_poll_event_queue_max++;
|
||||
uwsgi_poll_event_queue[eq]->poll = uwsgi_malloc(sizeof(struct pollfd) * uwsgi.max_fd);
|
||||
uwsgi_poll_event_queue[eq]->max_events = uwsgi.max_fd;
|
||||
pthread_mutex_init(&uwsgi_poll_event_queue[eq]->lock, NULL);
|
||||
return eq;
|
||||
}
|
||||
|
||||
void *event_queue_alloc(int nevents) {
|
||||
return uwsgi_calloc(sizeof(struct pollfd) * nevents);
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_read(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLIN) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_fd_write_to_readwrite(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLIN|POLLOUT;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int event_queue_fd_read_to_readwrite(int eq, int fd) {
|
||||
return event_queue_fd_write_to_readwrite(eq, fd);
|
||||
}
|
||||
|
||||
int event_queue_interesting_fd_is_write(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLOUT) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int event_queue_add_fd_read(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
if (uwsgi_poll_fd_is_registered(upe, fd)) {
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
int ret = uwsgi_poll_fd_add(upe, fd, POLLIN);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_add_fd_write(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
if (uwsgi_poll_fd_is_registered(upe, fd)) {
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
int ret = uwsgi_poll_fd_add(upe, fd, POLLOUT);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_del_fd(int eq, int fd, int event) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int ret = uwsgi_poll_fd_del(upe, fd);
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return ret;
|
||||
}
|
||||
int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
uwsgi_poll_queue_rebuild(upe);
|
||||
int ret = poll(upe->poll, upe->nevents, timeout * 1000);
|
||||
int cnt = 0;
|
||||
if (ret > 0) {
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].revents) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[cnt];
|
||||
upoll->fd = upe->poll[i].fd;
|
||||
upoll->revents = upe->poll[i].revents;
|
||||
upoll->events = upe->poll[i].events;
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
if (ret <= 0) return ret;
|
||||
return cnt;
|
||||
}
|
||||
int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
if (upoll->revents & POLLERR || upoll->revents & POLLHUP || upoll->revents & POLLNVAL) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
int event_queue_interesting_fd(void *events, int id) {
|
||||
struct pollfd *pevents = (struct pollfd *)events;
|
||||
struct pollfd *upoll = &pevents[id];
|
||||
return upoll->fd;
|
||||
}
|
||||
int event_queue_fd_write_to_read(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLIN;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
int event_queue_fd_read_to_write(int eq, int fd) {
|
||||
struct uwsgi_poll_event *upe = uwsgi_poll_event_queue[eq];
|
||||
pthread_mutex_lock(&upe->lock);
|
||||
int i;
|
||||
for(i=0;i<upe->nevents;i++) {
|
||||
if (upe->poll[i].fd == fd) {
|
||||
upe->poll[i].events = POLLOUT;
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&upe->lock);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
|
||||
#include <port.h>
|
||||
|
||||
+1
-5
@@ -1,6 +1,4 @@
|
||||
#ifdef UWSGI_INI
|
||||
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
@@ -157,5 +155,3 @@ void uwsgi_ini_config(char *file, char *magic_table[]) {
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -296,7 +296,7 @@ void uwsgi_commandline_config() {
|
||||
void uwsgi_setup_workers() {
|
||||
int i, j;
|
||||
// allocate shared memory for workers + master
|
||||
uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1 + uwsgi.grunt));
|
||||
uwsgi.workers = (struct uwsgi_worker *) uwsgi_calloc_shared(sizeof(struct uwsgi_worker) * (uwsgi.numproc + 1));
|
||||
|
||||
for (i = 0; i <= uwsgi.numproc; i++) {
|
||||
// allocate memory for apps
|
||||
|
||||
@@ -770,10 +770,10 @@ timeout:
|
||||
// check if an fd is valid
|
||||
int uwsgi_valid_fd(int fd) {
|
||||
int ret = fcntl(fd, F_GETFL);
|
||||
if (ret == 0) {
|
||||
return 1;
|
||||
if (ret == -1) {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void uwsgi_close_all_fds(void) {
|
||||
|
||||
+146
-6
@@ -75,6 +75,41 @@ void uwsgi_parse_legion(char *key, uint16_t keylen, char *value, uint16_t vallen
|
||||
memcpy(ul->lord_uuid, value, 36);
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_strncmp(key, keylen, "scroll", 6)) {
|
||||
ul->scroll = value;
|
||||
ul->scroll_len = vallen;
|
||||
}
|
||||
}
|
||||
|
||||
// this function is called when a node is added or removed (heavy locking is needed)
|
||||
static void legion_rebuild_scrolls(struct uwsgi_legion *ul) {
|
||||
uint64_t max_size = ul->scrolls_max_size;
|
||||
|
||||
// first, try to add myself
|
||||
if (ul->scroll_len + (uint64_t) 2 > max_size) {
|
||||
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
|
||||
ul->scroll_len = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
char *ptr = ul->scrolls;
|
||||
*ptr ++= (uint8_t) (ul->scroll_len & 0xff);
|
||||
*ptr ++= (uint8_t) ((ul->scroll_len >> 8) &0xff);
|
||||
memcpy(ptr, ul->scroll, ul->scroll_len); ptr += ul->scroll_len;
|
||||
ul->scrolls_len = 2 + ul->scroll_len;
|
||||
// ok start adding nodes;
|
||||
struct uwsgi_legion_node *uln = ul->nodes_head;
|
||||
while(uln) {
|
||||
if (ul->scrolls_len + 2 + uln->scroll_len > max_size) {
|
||||
uwsgi_log("[DANGER] you have configured a too much tiny buffer for the scrolls list !!! tune it with --legion-scroll-list-max-size\n");
|
||||
return;
|
||||
}
|
||||
*ptr ++= (uint8_t) (uln->scroll_len & 0xff);
|
||||
*ptr ++= (uint8_t) ((uln->scroll_len >> 8) &0xff);
|
||||
memcpy(ptr, uln->scroll, uln->scroll_len); ptr += uln->scroll_len;
|
||||
ul->scrolls_len += 2 + uln->scroll_len;
|
||||
uln = uln->next;
|
||||
}
|
||||
}
|
||||
|
||||
// critical section (remember to lock when you use it)
|
||||
@@ -100,6 +135,7 @@ struct uwsgi_legion_node *uwsgi_legion_add_node(struct uwsgi_legion *ul, uint16_
|
||||
ul->nodes_head = node;
|
||||
}
|
||||
|
||||
|
||||
return node;
|
||||
|
||||
|
||||
@@ -137,6 +173,8 @@ void uwsgi_legion_remove_node(struct uwsgi_legion *ul, struct uwsgi_legion_node
|
||||
}
|
||||
|
||||
free(node);
|
||||
|
||||
legion_rebuild_scrolls(ul);
|
||||
}
|
||||
|
||||
struct uwsgi_legion_node *uwsgi_legion_get_node(struct uwsgi_legion *ul, uint64_t valor, char *name, uint16_t name_len, char *uuid) {
|
||||
@@ -170,9 +208,9 @@ static void legions_check_nodes() {
|
||||
struct uwsgi_legion_node *tmp_node = node;
|
||||
node = node->next;
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s left Legion %s\n", tmp_node->name_len, tmp_node->name, tmp_node->valor, 36, tmp_node->uuid, legion->legion);
|
||||
pthread_mutex_lock(&legion->lock);
|
||||
uwsgi_wlock(legion->lock);
|
||||
uwsgi_legion_remove_node(legion, tmp_node);
|
||||
pthread_mutex_unlock(&legion->lock);
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
continue;
|
||||
}
|
||||
node = node->next;
|
||||
@@ -281,6 +319,15 @@ static void legions_check_nodes_step2() {
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
if (ul->scroll_len > 0 && ul->scroll_len <= ul->lord_scroll_size) {
|
||||
uwsgi_wlock(ul->lock);
|
||||
ul->lord_scroll_len = ul->scroll_len;
|
||||
memcpy(ul->lord_scroll, ul->scroll, ul->lord_scroll_len);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
}
|
||||
else {
|
||||
ul->lord_scroll_len = 0;
|
||||
}
|
||||
ul->i_am_the_lord = uwsgi_now();
|
||||
// trick: reduce the time needed by the old lord to unlord itself
|
||||
uwsgi_legion_announce(ul);
|
||||
@@ -289,6 +336,11 @@ static void legions_check_nodes_step2() {
|
||||
else {
|
||||
if (ul->i_am_the_lord) {
|
||||
uwsgi_log("[uwsgi-legion] a new Lord (valor: %llu uuid: %.*s) raised for Legion %s...\n", ul->lord_valor, 36, ul->lord_uuid, ul->legion);
|
||||
if (ul->lord_scroll_len > 0) {
|
||||
uwsgi_log("*********** The New Lord Scroll ***********\n\n");
|
||||
uwsgi_log("%.*s\n", ul->lord_scroll_len, ul->lord_scroll);
|
||||
uwsgi_log("\n*********** End of the New Lord Scroll ***********\n\n");
|
||||
}
|
||||
// no more lord, trigger unlord hooks
|
||||
struct uwsgi_string_list *usl = ul->unlord_hooks;
|
||||
while (usl) {
|
||||
@@ -354,6 +406,18 @@ struct uwsgi_legion_node *uwsgi_legion_get_lord(struct uwsgi_legion *ul) {
|
||||
ul->lord_valor = best_valor;
|
||||
memcpy(ul->lord_uuid, best_uuid, 36);
|
||||
|
||||
if (!best_node) return NULL;
|
||||
|
||||
if (best_node->scroll_len > 0 && best_node->scroll_len <= ul->lord_scroll_size) {
|
||||
uwsgi_wlock(ul->lock);
|
||||
ul->lord_scroll_len = best_node->scroll_len;
|
||||
memcpy(ul->lord_scroll, best_node->scroll, ul->lord_scroll_len);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
}
|
||||
else {
|
||||
ul->lord_scroll_len = 0;
|
||||
}
|
||||
|
||||
return best_node;
|
||||
}
|
||||
|
||||
@@ -483,9 +547,17 @@ static void *legion_loop(void *foobar) {
|
||||
struct uwsgi_legion_node *node = uwsgi_legion_get_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid);
|
||||
if (!node) {
|
||||
// add the new node
|
||||
pthread_mutex_lock(&ul->lock);
|
||||
uwsgi_wlock(ul->lock);
|
||||
node = uwsgi_legion_add_node(ul, legion_msg.valor, legion_msg.name, legion_msg.name_len, legion_msg.uuid);
|
||||
pthread_mutex_unlock(&ul->lock);
|
||||
if (!node) continue;
|
||||
if (legion_msg.scroll_len > 0) {
|
||||
node->scroll = uwsgi_malloc(legion_msg.scroll_len);
|
||||
node->scroll_len = legion_msg.scroll_len;
|
||||
memcpy(node->scroll, legion_msg.scroll, node->scroll_len);
|
||||
}
|
||||
// we are still locked (and safe), let's rebuild the scrolls list
|
||||
legion_rebuild_scrolls(ul);
|
||||
uwsgi_rwunlock(ul->lock);
|
||||
uwsgi_log("[uwsgi-legion] node: %.*s valor: %llu uuid: %.*s joined Legion %s\n", node->name_len, node->name, node->valor, 36, node->uuid, ul->legion);
|
||||
}
|
||||
|
||||
@@ -624,6 +696,11 @@ int uwsgi_legion_announce(struct uwsgi_legion *ul) {
|
||||
goto err;
|
||||
if (uwsgi_buffer_append_keyval(ub, "lord_uuid", 9, ul->lord_uuid, 36))
|
||||
goto err;
|
||||
|
||||
if (ul->scroll_len > 0) {
|
||||
if (uwsgi_buffer_append_keyval(ub, "scroll", 6, ul->scroll, ul->scroll_len))
|
||||
goto err;
|
||||
}
|
||||
#ifdef UWSGI_UUID
|
||||
#endif
|
||||
|
||||
@@ -716,8 +793,33 @@ void uwsgi_opt_legion_quorum(char *opt, char *value, void *foobar) {
|
||||
}
|
||||
|
||||
ul->quorum = atoi(space+1);
|
||||
free(legion);
|
||||
}
|
||||
|
||||
void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) {
|
||||
|
||||
char *legion = uwsgi_str(value);
|
||||
|
||||
char *space = strchr(legion, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid legion-scroll syntax, must be <legion> <scroll>\n");
|
||||
exit(1);
|
||||
}
|
||||
*space = 0;
|
||||
|
||||
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
|
||||
if (!ul) {
|
||||
uwsgi_log("unknown legion: %s\n", legion);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->scroll = space+1;
|
||||
ul->scroll_len = strlen(ul->scroll);
|
||||
// DO NOT FREE IT !!!
|
||||
//free(legion);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
|
||||
|
||||
@@ -867,7 +969,18 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
|
||||
ul->encrypt_ctx = ctx;
|
||||
ul->decrypt_ctx = ctx2;
|
||||
|
||||
pthread_mutex_init(&ul->lock, NULL);
|
||||
if (!uwsgi.legion_scroll_max_size) {
|
||||
uwsgi.legion_scroll_max_size = 4096;
|
||||
}
|
||||
|
||||
if (!uwsgi.legion_scroll_list_max_size) {
|
||||
uwsgi.legion_scroll_list_max_size = 32768;
|
||||
}
|
||||
|
||||
ul->lord_scroll_size = uwsgi.legion_scroll_max_size;
|
||||
ul->lord_scroll = uwsgi_calloc_shared(ul->lord_scroll_size);
|
||||
ul->scrolls_max_size = uwsgi.legion_scroll_list_max_size;
|
||||
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
|
||||
|
||||
uwsgi_legion_add(ul);
|
||||
}
|
||||
@@ -929,8 +1042,35 @@ next:
|
||||
|
||||
int uwsgi_legion_i_am_the_lord(char *name) {
|
||||
struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name);
|
||||
if (legion && legion->i_am_the_lord) {
|
||||
if (!legion) return 0;
|
||||
if (legion->i_am_the_lord) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *uwsgi_legion_lord_scroll(char *name, uint16_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name);
|
||||
if (!legion) return 0;
|
||||
uwsgi_rlock(legion->lock);
|
||||
if (legion->lord_scroll_len > 0) {
|
||||
buf = uwsgi_malloc(legion->lord_scroll_len);
|
||||
memcpy(buf, legion->lord_scroll, legion->lord_scroll_len);
|
||||
*rlen = legion->lord_scroll_len;
|
||||
}
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *uwsgi_legion_scrolls(char *name, uint64_t *rlen) {
|
||||
char *buf = NULL;
|
||||
struct uwsgi_legion *legion = uwsgi_legion_get_by_name(name);
|
||||
if (!legion) return NULL;
|
||||
uwsgi_rlock(legion->lock);
|
||||
buf = uwsgi_malloc(legion->scrolls_len);
|
||||
memcpy(buf, legion->scrolls, legion->scrolls_len);
|
||||
*rlen = legion->scrolls_len;
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
return buf;
|
||||
}
|
||||
|
||||
+63
@@ -401,6 +401,60 @@ void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_unlock_fast(uli);
|
||||
}
|
||||
|
||||
#elif defined(UWSGI_LOCK_USE_WINDOWS_MUTEX)
|
||||
|
||||
#define UWSGI_LOCK_ENGINE_NAME "windows mutexes"
|
||||
#define UWSGI_LOCK_SIZE sizeof(HANDLE)
|
||||
#define UWSGI_RWLOCK_SIZE sizeof(HANDLE)
|
||||
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
|
||||
|
||||
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
|
||||
struct _SECURITY_ATTRIBUTES sa;
|
||||
memset(&sa, 0, sizeof(struct _SECURITY_ATTRIBUTES));
|
||||
sa.bInheritHandle = 1;
|
||||
uli->lock_ptr = CreateMutex(&sa, FALSE, NULL);
|
||||
return uli;
|
||||
}
|
||||
|
||||
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
|
||||
WaitForSingleObject(uli->lock_ptr, INFINITE);
|
||||
uli->pid = uwsgi.mypid;
|
||||
}
|
||||
|
||||
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
|
||||
ReleaseMutex(uli->lock_ptr);
|
||||
uli->pid = 0;
|
||||
}
|
||||
|
||||
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
if (WaitForSingleObject(uli->lock_ptr, 0) == WAIT_TIMEOUT) {
|
||||
return 0;
|
||||
}
|
||||
return uli->pid;
|
||||
}
|
||||
|
||||
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
|
||||
return uwsgi_lock_fast_init(id);
|
||||
}
|
||||
|
||||
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_lock_fast(uli);
|
||||
}
|
||||
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_lock_fast(uli);
|
||||
}
|
||||
|
||||
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
|
||||
return uwsgi_lock_fast_check(uli);
|
||||
}
|
||||
|
||||
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
|
||||
uwsgi_unlock_fast(uli);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define uwsgi_lock_fast_init uwsgi_lock_ipcsem_init
|
||||
@@ -641,6 +695,15 @@ ready:
|
||||
}
|
||||
|
||||
uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
// register locking for legions
|
||||
struct uwsgi_legion *ul = uwsgi.legions;
|
||||
while(ul) {
|
||||
ul->lock = uwsgi_lock_init(uwsgi_concat2("legion_", ul->legion));
|
||||
ul = ul->next;
|
||||
}
|
||||
#endif
|
||||
uwsgi.locking_setup = 1;
|
||||
}
|
||||
|
||||
|
||||
+33
-12
@@ -1,9 +1,9 @@
|
||||
#define _NO_UWSGI_RB
|
||||
#include "uwsgi.h"
|
||||
|
||||
#ifndef __DragonFly__
|
||||
#include <uwsgi.h>
|
||||
#endif
|
||||
#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
|
||||
#include <kvm.h>
|
||||
#include <sys/user.h>
|
||||
#include <kvm.h>
|
||||
#elif defined(__sun__)
|
||||
/* Terrible Hack !!! */
|
||||
#ifndef _LP64
|
||||
@@ -17,6 +17,10 @@
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#ifdef __DragonFly__
|
||||
#include <uwsgi.h>
|
||||
#endif
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
//use this instead of fprintf to avoid buffering mess with udp logging
|
||||
@@ -314,7 +318,7 @@ static struct uwsgi_logger *setup_choosen_logger(struct uwsgi_string_list *usl)
|
||||
int is_id = 1;
|
||||
int i;
|
||||
for (i = 0; i < (space - name); i++) {
|
||||
if (!isalnum(name[i])) {
|
||||
if (!isalnum((int)name[i])) {
|
||||
is_id = 0;
|
||||
break;
|
||||
}
|
||||
@@ -638,12 +642,8 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_MEMORY_DEBUG] == 1) {
|
||||
#ifndef UNBIT
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
#else
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
|
||||
#endif
|
||||
|
||||
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} {rss usage: %llu bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024,
|
||||
(unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].rss_size / 1024 / 1024);
|
||||
logvec[logvecpos].iov_base = mempkt;
|
||||
logvec[logvecpos].iov_len = rlen;
|
||||
logvecpos++;
|
||||
@@ -673,7 +673,11 @@ void uwsgi_logit_simple(struct wsgi_request *wsgi_req) {
|
||||
void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
|
||||
#ifdef UNBIT
|
||||
*vsz = syscall(356);
|
||||
uint64_t ret[2];
|
||||
ret[0] = 0; ret[1] = 0;
|
||||
syscall(358, ret);
|
||||
*vsz = ret[0];
|
||||
*rss = ret[1] * uwsgi.page_size;
|
||||
#elif defined(__linux__)
|
||||
FILE *procfile;
|
||||
int i;
|
||||
@@ -686,6 +690,18 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
fclose(procfile);
|
||||
}
|
||||
*rss = *rss * uwsgi.page_size;
|
||||
#elif defined(__CYGWIN__)
|
||||
// same as Linux but rss is not in pages...
|
||||
FILE *procfile;
|
||||
int i;
|
||||
procfile = fopen("/proc/self/stat", "r");
|
||||
if (procfile) {
|
||||
i = fscanf(procfile, "%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
|
||||
if (i != 2) {
|
||||
uwsgi_log("warning: invalid record in /proc/self/stat\n");
|
||||
}
|
||||
fclose(procfile);
|
||||
}
|
||||
#elif defined (__sun__)
|
||||
psinfo_t info;
|
||||
int procfd;
|
||||
@@ -725,8 +741,13 @@ void get_memusage(uint64_t * rss, uint64_t * vsz) {
|
||||
struct kinfo_proc *kproc;
|
||||
kproc = kvm_getprocs(kv, KERN_PROC_PID, uwsgi.mypid, &cnt);
|
||||
if (kproc && cnt > 0) {
|
||||
#if defined(__FreeBSD__)
|
||||
*vsz = kproc->ki_size;
|
||||
*rss = kproc->ki_rssize * uwsgi.page_size;
|
||||
#elif defined(__DragonFly__)
|
||||
*vsz = kproc->kp_vm_map_size;
|
||||
*rss = kproc->kp_vm_rssize * uwsgi.page_size;
|
||||
#endif
|
||||
}
|
||||
#elif defined(UWSGI_NEW_OPENBSD)
|
||||
struct kinfo_proc *kproc;
|
||||
|
||||
+3
-3
@@ -1312,7 +1312,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_list_open(us))
|
||||
goto end;
|
||||
|
||||
pthread_mutex_lock(&legion->lock);
|
||||
uwsgi_rlock(legion->lock);
|
||||
struct uwsgi_legion_node *node = legion->nodes_head;
|
||||
while (node) {
|
||||
if (uwsgi_stats_object_open(us))
|
||||
@@ -1342,7 +1342,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto unlock_legion_mutex;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&legion->lock);
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
|
||||
if (uwsgi_stats_list_close(us))
|
||||
goto end;
|
||||
@@ -1371,7 +1371,7 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
#ifdef UWSGI_SSL
|
||||
unlock_legion_mutex:
|
||||
if (legion)
|
||||
pthread_mutex_unlock(&legion->lock);
|
||||
uwsgi_rwunlock(legion->lock);
|
||||
#endif
|
||||
end:
|
||||
free(us->base);
|
||||
|
||||
@@ -437,6 +437,7 @@ void uwsgi_setup_mules_and_farms() {
|
||||
mules_list++;
|
||||
|
||||
strncpy(uwsgi.farms[i].name, farm_value, 0xff);
|
||||
free(farm_value);
|
||||
|
||||
// create the socket pipe
|
||||
create_signal_pipe(uwsgi.farms[i].signal_pipe);
|
||||
|
||||
+87
-53
@@ -28,13 +28,6 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
|
||||
|
||||
struct uwsgi_header *uh;
|
||||
|
||||
if (message) {
|
||||
uh = (struct uwsgi_header *) message;
|
||||
}
|
||||
else {
|
||||
uh = (struct uwsgi_header *) uwsgi_malloc(4);
|
||||
}
|
||||
|
||||
udp_port = strchr(host, ':');
|
||||
if (udp_port) {
|
||||
udp_port[0] = 0;
|
||||
@@ -64,6 +57,13 @@ ssize_t send_udp_message(uint8_t modifier1, uint8_t modifier2, char *host, char
|
||||
|
||||
}
|
||||
|
||||
if (message) {
|
||||
uh = (struct uwsgi_header *) message;
|
||||
}
|
||||
else {
|
||||
uh = (struct uwsgi_header *) uwsgi_malloc(4);
|
||||
}
|
||||
|
||||
uh->modifier1 = modifier1;
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uh->pktsize = uwsgi_swap16(message_size);
|
||||
@@ -578,7 +578,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
ptrbuf = buffer;
|
||||
bufferend = ptrbuf + wsgi_req->uh->pktsize;
|
||||
int i;
|
||||
|
||||
|
||||
/* set an HTTP 500 status as default */
|
||||
wsgi_req->status = 500;
|
||||
|
||||
@@ -673,7 +673,6 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
|
||||
|
||||
next:
|
||||
|
||||
|
||||
// manage post buffering (if needed as post_file could be created before)
|
||||
if (uwsgi.post_buffering > 0 && !wsgi_req->post_file) {
|
||||
// read to disk if post_cl > post_buffering (it will eventually do upload progress...)
|
||||
@@ -759,12 +758,7 @@ next:
|
||||
}
|
||||
|
||||
|
||||
// check for static files
|
||||
|
||||
// skip methods other than GET and HEAD
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
return 0;
|
||||
}
|
||||
/* CHECK FOR STATIC FILES */
|
||||
|
||||
// skip extensions
|
||||
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
|
||||
@@ -886,44 +880,6 @@ nextsm2:
|
||||
return 0;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_send_empty_pkt(int fd, char *socket_name, uint8_t modifier1, uint8_t modifier2) {
|
||||
|
||||
struct uwsgi_header uh;
|
||||
char *port;
|
||||
uint16_t s_port;
|
||||
struct sockaddr_in uaddr;
|
||||
int ret;
|
||||
|
||||
uh.modifier1 = modifier1;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = modifier2;
|
||||
|
||||
if (socket_name) {
|
||||
port = strchr(socket_name, ':');
|
||||
if (!port)
|
||||
return -1;
|
||||
s_port = atoi(port + 1);
|
||||
port[0] = 0;
|
||||
memset(&uaddr, 0, sizeof(struct sockaddr_in));
|
||||
uaddr.sin_family = AF_INET;
|
||||
uaddr.sin_addr.s_addr = inet_addr(socket_name);
|
||||
uaddr.sin_port = htons(s_port);
|
||||
|
||||
port[0] = ':';
|
||||
|
||||
ret = sendto(fd, &uh, 4, 0, (struct sockaddr *) &uaddr, sizeof(struct sockaddr_in));
|
||||
}
|
||||
else {
|
||||
ret = send(fd, &uh, 4, 0);
|
||||
}
|
||||
|
||||
if (ret < 0) {
|
||||
uwsgi_error("sendto()");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_hooked_parse(char *buffer, size_t len, void (*hook) (char *, uint16_t, char *, uint16_t, void *), void *data) {
|
||||
|
||||
char *ptrbuf, *bufferend;
|
||||
@@ -1005,9 +961,24 @@ int uwsgi_hooked_parse_array(char *buffer, size_t len, void (*hook) (uint16_t, c
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
the following functions need to take in account that POST data could be already available in wsgi_req->buffer (generally when uwsgi protocol is in use)
|
||||
|
||||
In such a case, allocate a proto_parser_buf and move data there
|
||||
|
||||
*/
|
||||
|
||||
char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, char *val, uint16_t vallen) {
|
||||
|
||||
if (!wsgi_req->proto_parser_buf) {
|
||||
if (wsgi_req->proto_parser_remains > 0) {
|
||||
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
|
||||
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
|
||||
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
|
||||
}
|
||||
}
|
||||
|
||||
if ((wsgi_req->uh->pktsize + (2 + keylen + 2 + vallen)) > uwsgi.buffer_size) {
|
||||
uwsgi_log("not enough buffer space to add %.*s variable, consider increasing it with the --buffer-size option\n", keylen, key);
|
||||
return NULL;
|
||||
@@ -1043,3 +1014,66 @@ char *uwsgi_req_append(struct wsgi_request *wsgi_req, char *key, uint16_t keylen
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
int uwsgi_req_append_path_info_with_index(struct wsgi_request *wsgi_req, char *index, uint16_t index_len) {
|
||||
|
||||
if (!wsgi_req->proto_parser_buf) {
|
||||
if (wsgi_req->proto_parser_remains > 0) {
|
||||
wsgi_req->proto_parser_buf = uwsgi_malloc(wsgi_req->proto_parser_remains);
|
||||
memcpy(wsgi_req->proto_parser_buf, wsgi_req->proto_parser_remains_buf, wsgi_req->proto_parser_remains);
|
||||
wsgi_req->proto_parser_remains_buf = wsgi_req->proto_parser_buf;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t need_slash = 0;
|
||||
if (wsgi_req->path_info_len > 0) {
|
||||
if (wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
|
||||
need_slash = 1;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->path_info_len += need_slash + index_len;
|
||||
|
||||
// 2 + 9 + 2
|
||||
if ((wsgi_req->uh->pktsize + (13 + wsgi_req->path_info_len)) > uwsgi.buffer_size) {
|
||||
uwsgi_log("not enough buffer space to transform the PATH_INFO variable, consider increasing it with the --buffer-size option\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (wsgi_req->var_cnt >= uwsgi.vec_size - (4 + 2)) {
|
||||
uwsgi_log("max vec size reached for PATH_INFO + index. skip this request.\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint16_t keylen = 9;
|
||||
char *ptr = wsgi_req->buffer + wsgi_req->uh->pktsize;
|
||||
*ptr++ = (uint8_t) (keylen & 0xff);
|
||||
*ptr++ = (uint8_t) ((keylen >> 8) & 0xff);
|
||||
|
||||
memcpy(ptr, "PATH_INFO", keylen);
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = ptr;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = keylen;
|
||||
wsgi_req->var_cnt++;
|
||||
ptr += keylen;
|
||||
|
||||
*ptr++ = (uint8_t) (wsgi_req->path_info_len & 0xff);
|
||||
*ptr++ = (uint8_t) ((wsgi_req->path_info_len >> 8) & 0xff);
|
||||
|
||||
char *new_path_info = ptr;
|
||||
|
||||
memcpy(ptr, wsgi_req->path_info, wsgi_req->path_info_len - (need_slash + index_len));
|
||||
ptr+=wsgi_req->path_info_len - (need_slash + index_len);
|
||||
if (need_slash) {
|
||||
*ptr ++= '/';
|
||||
}
|
||||
memcpy(ptr, index, index_len);
|
||||
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_base = new_path_info;
|
||||
wsgi_req->hvec[wsgi_req->var_cnt].iov_len = wsgi_req->path_info_len;
|
||||
wsgi_req->var_cnt++;
|
||||
|
||||
wsgi_req->uh->pktsize += 13 + wsgi_req->path_info_len;
|
||||
wsgi_req->path_info = new_path_info;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ void uwsgi_init_queue() {
|
||||
// fix header
|
||||
uwsgi.queue_header = uwsgi.queue;
|
||||
uwsgi.queue += 16;
|
||||
close(queue_fd);
|
||||
}
|
||||
else {
|
||||
uwsgi.queue = mmap(NULL, (uwsgi.queue_blocksize * uwsgi.queue_size) + 16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
|
||||
|
||||
+139
-15
@@ -72,8 +72,9 @@ struct uwsgi_buffer *uwsgi_routing_translate(struct wsgi_request *wsgi_req, stru
|
||||
}
|
||||
|
||||
// add the final NULL byte (to simplify plugin work)
|
||||
|
||||
if (uwsgi_buffer_append(ub, "\0", 1)) goto error;
|
||||
// .. but came back of 1 position to avoid accounting it
|
||||
ub->pos--;
|
||||
|
||||
if (pass1 != data) {
|
||||
free(pass1);
|
||||
@@ -85,17 +86,21 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) {
|
||||
int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) {
|
||||
|
||||
struct uwsgi_route *routes = uwsgi.routes;
|
||||
void *goon_func = NULL;
|
||||
int n = -1;
|
||||
|
||||
char *orig_subject = subject;
|
||||
uint16_t orig_subject_len = subject_len;
|
||||
|
||||
while (routes) {
|
||||
|
||||
if (wsgi_req->route_goto > 0 && wsgi_req->route_pc < wsgi_req->route_goto) {
|
||||
goto next;
|
||||
}
|
||||
|
||||
if (goon_func && goon_func == routes->func) {
|
||||
goto next;
|
||||
}
|
||||
@@ -149,6 +154,8 @@ static int uwsgi_apply_routes_do(struct wsgi_request *wsgi_req, char *subject, u
|
||||
}
|
||||
}
|
||||
next:
|
||||
subject = orig_subject;
|
||||
subject_len = orig_subject_len;
|
||||
routes = routes->next;
|
||||
if (routes) wsgi_req->route_pc++;
|
||||
}
|
||||
@@ -169,28 +176,21 @@ int uwsgi_apply_routes(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
// in case of static files serving previous rules could be applied
|
||||
if (wsgi_req->routes_applied) {
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
}
|
||||
|
||||
return uwsgi_apply_routes_do(wsgi_req, NULL, 0);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_apply_routes_fast(struct wsgi_request *wsgi_req, char *subject, uint16_t subject_len) {
|
||||
|
||||
if (!uwsgi.routes)
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
|
||||
// avoid loops
|
||||
if (wsgi_req->is_routing)
|
||||
return UWSGI_ROUTE_CONTINUE;
|
||||
|
||||
return uwsgi_apply_routes_do(wsgi_req, subject, subject_len);
|
||||
}
|
||||
|
||||
static void *uwsgi_route_get_condition_func(char *name) {
|
||||
struct uwsgi_route_condition *urc = uwsgi.route_conditions;
|
||||
while(urc) {
|
||||
if (!strcmp(urc->name, name)) {
|
||||
return urc->func;
|
||||
}
|
||||
urc = urc->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -344,12 +344,14 @@ int uwsgi_route_api_func(struct wsgi_request *wsgi_req, char *router, char *args
|
||||
}
|
||||
r = r->next;
|
||||
}
|
||||
free(args);
|
||||
return -1;
|
||||
found:
|
||||
ur = uwsgi_calloc(sizeof(struct uwsgi_route));
|
||||
// initialize the virtual route
|
||||
if (r->func(ur, args)) {
|
||||
free(ur);
|
||||
free(args);
|
||||
return -1;
|
||||
}
|
||||
// call it
|
||||
@@ -358,6 +360,7 @@ found:
|
||||
ur->free(ur);
|
||||
}
|
||||
free(ur);
|
||||
free(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -625,6 +628,119 @@ static int uwsgi_route_condition_isfile(struct wsgi_request *wsgi_req, struct uw
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_regexp(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
pcre *pattern;
|
||||
pcre_extra *pattern_extra;
|
||||
char *re = uwsgi_concat2n(semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str), "", 0);
|
||||
if (uwsgi_regexp_build(re, &pattern, &pattern_extra)) {
|
||||
free(re);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
free(re);
|
||||
|
||||
if (uwsgi_regexp_match(pattern, pattern_extra, ub->buf, ub->pos) >= 0) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
pcre_free(pattern);
|
||||
#ifdef PCRE_STUDY_JIT_COMPILE
|
||||
pcre_free_study(pattern_extra);
|
||||
#else
|
||||
pcre_free(pattern_extra);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
pcre_free(pattern);
|
||||
#ifdef PCRE_STUDY_JIT_COMPILE
|
||||
pcre_free_study(pattern_extra);
|
||||
#else
|
||||
pcre_free(pattern_extra);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_route_condition_equal(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!uwsgi_strncmp(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_startswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!uwsgi_starts_with(ub->buf, ub->pos, ub2->buf, ub2->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_route_condition_endswith(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
char *semicolon = memchr(ur->subject_str, ';', ur->subject_str_len);
|
||||
if (!semicolon) return 0;
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, semicolon - ur->subject_str);
|
||||
if (!ub) return -1;
|
||||
|
||||
struct uwsgi_buffer *ub2 = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, semicolon+1, ur->subject_str_len - ((semicolon+1) - ur->subject_str));
|
||||
if (!ub2) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ub2->pos < ub->pos) goto zero;
|
||||
if(!uwsgi_strncmp(ub->buf + (ub->pos - ub2->pos), ub2->pos, ub2->buf, ub2->pos)) {
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
zero:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
uwsgi_buffer_destroy(ub2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int uwsgi_route_condition_isdir(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, NULL, 0, ur->subject_str, ur->subject_str_len);
|
||||
if (!ub) return -1;
|
||||
@@ -682,6 +798,14 @@ void uwsgi_register_embedded_routers() {
|
||||
uwsgi_register_route_condition("isdir", uwsgi_route_condition_isdir);
|
||||
uwsgi_register_route_condition("islink", uwsgi_route_condition_islink);
|
||||
uwsgi_register_route_condition("isexec", uwsgi_route_condition_isexec);
|
||||
uwsgi_register_route_condition("equal", uwsgi_route_condition_equal);
|
||||
uwsgi_register_route_condition("isequal", uwsgi_route_condition_equal);
|
||||
uwsgi_register_route_condition("eq", uwsgi_route_condition_equal);
|
||||
uwsgi_register_route_condition("==", uwsgi_route_condition_equal);
|
||||
uwsgi_register_route_condition("startswith", uwsgi_route_condition_startswith);
|
||||
uwsgi_register_route_condition("endswith", uwsgi_route_condition_endswith);
|
||||
uwsgi_register_route_condition("regexp", uwsgi_route_condition_regexp);
|
||||
uwsgi_register_route_condition("re", uwsgi_route_condition_regexp);
|
||||
}
|
||||
|
||||
struct uwsgi_router *uwsgi_register_router(char *name, int (*func) (struct uwsgi_route *, char *)) {
|
||||
|
||||
@@ -123,6 +123,16 @@ void uwsgi_setup_inherited_sockets() {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_req_log_pipe[0] > -1) {
|
||||
if (j == uwsgi.shared->worker_req_log_pipe[0])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.shared->worker_req_log_pipe[1] > -1) {
|
||||
if (j == uwsgi.shared->worker_req_log_pipe[1])
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uwsgi.original_log_fd > -1) {
|
||||
if (j == uwsgi.original_log_fd)
|
||||
continue;
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
|
||||
int i;
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
int pos = (i * 256);
|
||||
memcpy(&uwsgi.shared->signal_table[pos], use, sizeof(struct uwsgi_signal_entry) * 256);
|
||||
memcpy(&uwsgi.shared->signal_table[pos], &uwsgi.shared->signal_table[0], sizeof(struct uwsgi_signal_entry) * 256);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+33
-1
@@ -2,6 +2,23 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int uwsgi_socket_strcmp(char *sock1, char *sock2) {
|
||||
size_t sock1_len = strlen(sock1);
|
||||
size_t sock2_len = strlen(sock2);
|
||||
|
||||
if (!uwsgi_starts_with(sock1, sock1_len, "0.0.0.0:", 8)) {
|
||||
sock1 += 7;
|
||||
sock1_len = strlen(sock1);
|
||||
}
|
||||
|
||||
if (!uwsgi_starts_with(sock2, sock2_len, "0.0.0.0:", 8)) {
|
||||
sock2 += 7;
|
||||
sock2_len = strlen(sock2);
|
||||
}
|
||||
|
||||
return uwsgi_strncmp(sock1, sock1_len, sock2, sock2_len);
|
||||
}
|
||||
|
||||
char *uwsgi_getsockname(int fd) {
|
||||
|
||||
socklen_t socket_type_len = sizeof(struct sockaddr_un);
|
||||
@@ -49,6 +66,7 @@ int bind_to_unix_dgram(char *socket_name) {
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
@@ -68,6 +86,7 @@ int bind_to_unix_dgram(char *socket_name) {
|
||||
#endif
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return serverfd;
|
||||
@@ -83,6 +102,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (strlen(socket_name) > 102) {
|
||||
uwsgi_log("invalid socket name\n");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (socket_name[0] == '@') {
|
||||
@@ -96,6 +116,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (uws_addr == NULL) {
|
||||
uwsgi_error("malloc()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(uws_addr, 0, sizeof(struct sockaddr_un));
|
||||
@@ -103,6 +124,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
if (abstract_socket == 0) {
|
||||
if (unlink(socket_name) != 0 && errno != ENOENT) {
|
||||
@@ -140,12 +162,14 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
|
||||
#endif
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// chmod unix socket for lazy users
|
||||
@@ -561,11 +585,13 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (serverfd < 0) {
|
||||
uwsgi_error("socket()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEADDR setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -576,6 +602,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_IP, IP_FREEBIND, (const void *) &uwsgi.freebind, sizeof(int)) < 0) {
|
||||
uwsgi_error("IP_FREEBIND setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -585,6 +612,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &uwsgi.reuse_port, sizeof(int)) < 0) {
|
||||
uwsgi_error("SO_REUSEPORT setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
|
||||
@@ -611,6 +639,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_SNDTIMEO, (const void *) &tv, sizeof(struct timeval)) < 0) {
|
||||
uwsgi_error("SO_SNDTIMEO setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -645,6 +674,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
}
|
||||
uwsgi_error("bind()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -652,12 +682,14 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
if (somaxconn > 0 && uwsgi.listen_queue > somaxconn) {
|
||||
uwsgi_log("Listen queue size is greater than the system max net.core.somaxconn (%li).\n", somaxconn);
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (listen(serverfd, listen_queue) != 0) {
|
||||
uwsgi_error("listen()");
|
||||
uwsgi_nuclear_blast();
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -1476,7 +1508,7 @@ void uwsgi_setup_shared_sockets() {
|
||||
for (i = 3; i < (int) uwsgi.max_fd; i++) {
|
||||
char *sock = uwsgi_getsockname(i);
|
||||
if (sock) {
|
||||
if (!strcmp(sock, shared_sock->name)) {
|
||||
if (!uwsgi_socket_strcmp(sock, shared_sock->name)) {
|
||||
if (strchr(sock, ':')) {
|
||||
uwsgi_log("uwsgi shared socket %d inherited TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), sock, i);
|
||||
shared_sock->family = AF_INET;
|
||||
|
||||
+25
-7
@@ -393,7 +393,7 @@ ssize_t uwsgi_append_static_path(char *dir, size_t dir_len, char *file, size_t f
|
||||
return len;
|
||||
}
|
||||
|
||||
int uwsgi_static_stat(char *filename, size_t *filename_len, struct stat *st) {
|
||||
static int uwsgi_static_stat(struct wsgi_request *wsgi_req, char *filename, size_t *filename_len, struct stat *st, struct uwsgi_string_list **index) {
|
||||
|
||||
int ret = stat(filename, st);
|
||||
// if non-existant return -1
|
||||
@@ -412,7 +412,8 @@ int uwsgi_static_stat(char *filename, size_t *filename_len, struct stat *st) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("checking for %s\n", filename);
|
||||
#endif
|
||||
if (!uwsgi_static_stat(filename, filename_len, st)) {
|
||||
if (uwsgi_is_file2(filename, st)) {
|
||||
*index = usl;
|
||||
*filename_len = new_len;
|
||||
return 0;
|
||||
}
|
||||
@@ -521,6 +522,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
char *filename = NULL;
|
||||
size_t filename_len = 0;
|
||||
|
||||
struct uwsgi_string_list *index = NULL;
|
||||
|
||||
if (!is_a_file) {
|
||||
filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
|
||||
@@ -580,23 +582,39 @@ found:
|
||||
|
||||
safe:
|
||||
|
||||
if (!uwsgi_static_stat(real_filename, &real_filename_len, &st)) {
|
||||
if (!uwsgi_static_stat(wsgi_req, real_filename, &real_filename_len, &st, &index)) {
|
||||
|
||||
if (index) {
|
||||
// if we are here the PATH_INFO need to be changed
|
||||
if (uwsgi_req_append_path_info_with_index(wsgi_req, index->value, index->len)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// skip methods other than GET and HEAD
|
||||
if (uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "GET", 3) && uwsgi_strncmp(wsgi_req->method, wsgi_req->method_len, "HEAD", 4)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// check for skippable ext
|
||||
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
|
||||
while (sse) {
|
||||
if (real_filename_len >= sse->len) {
|
||||
if (!uwsgi_strncmp(real_filename + (real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes_fast(wsgi_req, real_filename, real_filename_len) == UWSGI_ROUTE_BREAK)
|
||||
return 0;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sse = sse->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// before sending the file, we need to check if some rule applies
|
||||
if (!wsgi_req->is_routing && uwsgi_apply_routes_do(wsgi_req, NULL, 0) == UWSGI_ROUTE_BREAK) {
|
||||
return 0;
|
||||
}
|
||||
wsgi_req->routes_applied = 1;
|
||||
#endif
|
||||
|
||||
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
|
||||
}
|
||||
|
||||
|
||||
+45
-1
@@ -315,6 +315,45 @@ int uwsgi_stats_keylong_comma(struct uwsgi_stats *us, char *key, unsigned long l
|
||||
return uwsgi_stats_comma(us);
|
||||
}
|
||||
|
||||
int uwsgi_stats_keyslong(struct uwsgi_stats *us, char *key, long long num) {
|
||||
|
||||
if (uwsgi_stats_apply_tabs(us))
|
||||
return -1;
|
||||
|
||||
char *ptr = us->base + us->pos;
|
||||
char *watermark = us->base + us->size;
|
||||
size_t available = watermark - ptr;
|
||||
|
||||
int ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
while (ret >= (int) available) {
|
||||
char *new_base = realloc(us->base, us->size + us->chunk);
|
||||
if (!new_base)
|
||||
return -1;
|
||||
us->base = new_base;
|
||||
us->size += us->chunk;
|
||||
ptr = us->base + us->pos;
|
||||
watermark = us->base + us->size;
|
||||
available = watermark - ptr;
|
||||
ret = snprintf(ptr, available, "\"%s\":%lld", key, num);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
us->pos += ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_stats_keyslong_comma(struct uwsgi_stats *us, char *key, long long num) {
|
||||
int ret = uwsgi_stats_keyslong(us, key, num);
|
||||
if (ret)
|
||||
return -1;
|
||||
return uwsgi_stats_comma(us);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_send_stats(int fd, struct uwsgi_stats *(*func) (void)) {
|
||||
|
||||
struct sockaddr_un client_src;
|
||||
@@ -383,7 +422,10 @@ struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pu
|
||||
|
||||
uspi = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_instance));
|
||||
uspi->pusher = pusher;
|
||||
uspi->arg = arg;
|
||||
if (arg) {
|
||||
uspi->arg = uwsgi_str(arg);
|
||||
}
|
||||
uspi->raw = pusher->raw;
|
||||
if (old_uspi) {
|
||||
old_uspi->next = uspi;
|
||||
}
|
||||
@@ -452,6 +494,7 @@ void uwsgi_stats_pusher_setup() {
|
||||
pusher = uwsgi_stats_pusher_get(ssp);
|
||||
if (!pusher) {
|
||||
uwsgi_log("unable to find \"%s\" stats_pusher\n", ssp);
|
||||
free(ssp);
|
||||
exit(1);
|
||||
}
|
||||
char *arg = NULL;
|
||||
@@ -461,6 +504,7 @@ void uwsgi_stats_pusher_setup() {
|
||||
}
|
||||
uwsgi_stats_pusher_add(pusher, arg);
|
||||
usl = usl->next;
|
||||
free(ssp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+37
-5
@@ -659,7 +659,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
// defunct process reaper
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_REAPER] == 1 || uwsgi.grunt) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_REAPER] == 1) {
|
||||
while (waitpid(WAIT_ANY, &waitpid_status, WNOHANG) > 0);
|
||||
}
|
||||
|
||||
@@ -1248,6 +1248,16 @@ int uwsgi_is_file(char *filename) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_is_file2(char *filename, struct stat *st) {
|
||||
if (stat(filename, st)) {
|
||||
return 0;
|
||||
}
|
||||
if (S_ISREG(st->st_mode))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_is_dir(char *filename) {
|
||||
struct stat st;
|
||||
if (stat(filename, &st)) {
|
||||
@@ -1504,7 +1514,7 @@ void add_exported_option(char *key, char *value, int configured) {
|
||||
|
||||
while (blacklist) {
|
||||
if (!strcmp(key, blacklist->value)) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\"\n", key);
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
blacklist = blacklist->next;
|
||||
@@ -1520,11 +1530,25 @@ void add_exported_option(char *key, char *value, int configured) {
|
||||
whitelist = whitelist->next;
|
||||
}
|
||||
if (!allowed) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\"\n", key);
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.blacklist_context) {
|
||||
if (uwsgi_list_has_str(uwsgi.blacklist_context, key)) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by blacklist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.whitelist_context) {
|
||||
if (!uwsgi_list_has_str(uwsgi.whitelist_context, key)) {
|
||||
uwsgi_log("uWSGI error: forbidden option \"%s\" (by whitelist)\n", key);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.logic_opt_running)
|
||||
goto add;
|
||||
|
||||
@@ -1839,7 +1863,7 @@ int uwsgi_list_has_num(char *list, int num) {
|
||||
|
||||
int uwsgi_list_has_str(char *list, char *str) {
|
||||
|
||||
char *list2 = uwsgi_concat2(list + 1, "");
|
||||
char *list2 = uwsgi_str(list);
|
||||
|
||||
char *p = strtok(list2, " ");
|
||||
while (p != NULL) {
|
||||
@@ -2446,13 +2470,19 @@ void uwsgi_chown(char *filename, char *owner) {
|
||||
|
||||
char *uwsgi_get_binary_path(char *argvzero) {
|
||||
|
||||
#if defined(__linux__)
|
||||
#if defined(__linux__) || defined(__CYGWIN__)
|
||||
char *buf = uwsgi_calloc(PATH_MAX + 1);
|
||||
ssize_t len = readlink("/proc/self/exe", buf, PATH_MAX);
|
||||
if (len > 0) {
|
||||
return buf;
|
||||
}
|
||||
free(buf);
|
||||
#elif defined(_WIN32)
|
||||
char *buf = uwsgi_calloc(PATH_MAX + 1);
|
||||
if (GetModuleFileName(NULL, buf, PATH_MAX) > 0) {
|
||||
return buf;
|
||||
}
|
||||
free(buf);
|
||||
#elif defined(__NetBSD__)
|
||||
char *buf = uwsgi_calloc(PATH_MAX + 1);
|
||||
ssize_t len = readlink("/proc/curproc/exe", buf, PATH_MAX);
|
||||
@@ -2917,11 +2947,13 @@ pid_t uwsgi_fork(char *name) {
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
if (uwsgi.never_swap) {
|
||||
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
|
||||
uwsgi_error("mlockall()");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__linux__) || defined(__sun__)
|
||||
int i;
|
||||
|
||||
+61
-20
@@ -109,6 +109,12 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
|
||||
{"endif", optional_argument, 0, "(opt logic) end if", uwsgi_opt_noop, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"blacklist", required_argument, 0, "set options blacklist context", uwsgi_opt_set_str, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-blacklist", no_argument, 0, "clear options blacklist context", uwsgi_opt_set_null, &uwsgi.blacklist_context, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"whitelist", required_argument, 0, "set options whitelist context", uwsgi_opt_set_str, &uwsgi.whitelist_context, UWSGI_OPT_IMMEDIATE},
|
||||
{"end-whitelist", no_argument, 0, "clear options whitelist context", uwsgi_opt_set_null, &uwsgi.whitelist_context, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"ignore-sigpipe", no_argument, 0, "do not report (annoying) SIGPIPE", uwsgi_opt_true, &uwsgi.ignore_sigpipe, 0},
|
||||
{"ignore-write-errors", no_argument, 0, "do not report (annoying) write()/writev() errors", uwsgi_opt_true, &uwsgi.ignore_write_errors, 0},
|
||||
{"write-errors-tolerance", required_argument, 0, "set the maximum number of allowed write errors (default: no tolerance)", uwsgi_opt_set_64bit, &uwsgi.write_errors_tolerance, 0},
|
||||
@@ -170,6 +176,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"emperor-throttle", required_argument, 0, "set throttling level (in milliseconds) for bad behaving vassals (default 1000)", uwsgi_opt_set_int, &uwsgi.emperor_throttle, 0},
|
||||
{"emperor-max-throttle", required_argument, 0, "set max throttling level (in milliseconds) for bad behaving vassals (default 3 minutes)", uwsgi_opt_set_int, &uwsgi.emperor_max_throttle, 0},
|
||||
{"emperor-magic-exec", no_argument, 0, "prefix vassals config files with exec:// if they have the executable bit", uwsgi_opt_true, &uwsgi.emperor_magic_exec, 0},
|
||||
{"emperor-on-demand-extension", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
|
||||
{"emperor-on-demand-ext", required_argument, 0, "search for text file (vassal name + extension) containing the on demand socket name", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_extension, 0},
|
||||
{"emperor-on-demand-directory", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-dir", required_argument, 0, "enable on demand mode binding to the unix socket in the specified directory named like the vassal + .socket", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_directory, 0},
|
||||
{"emperor-on-demand-exec", required_argument, 0, "use the output of the specified command as on demand socket name (the vassal name is passed as the only argument)", uwsgi_opt_set_str, &uwsgi.emperor_on_demand_exec, 0},
|
||||
{"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0},
|
||||
{"vassals-inherit", required_argument, 0, "add config templates to vassals config", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0},
|
||||
@@ -264,9 +275,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"exec-as-user", required_argument, 0, "run the specified command after privileges drop", uwsgi_opt_add_string_list, &uwsgi.exec_as_user, 0},
|
||||
{"exec-as-user-atexit", required_argument, 0, "run the specified command before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.exec_as_user_atexit, 0},
|
||||
{"exec-pre-app", required_argument, 0, "run the specified command before app loading", uwsgi_opt_add_string_list, &uwsgi.exec_pre_app, 0},
|
||||
#ifdef UWSGI_INI
|
||||
{"exec-post-app", required_argument, 0, "run the specified command after app loading", uwsgi_opt_add_string_list, &uwsgi.exec_post_app, 0},
|
||||
{"ini", required_argument, 0, "load config from ini file", uwsgi_opt_load_ini, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_YAML
|
||||
{"yaml", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"yal", required_argument, 'y', "load config from yaml file", uwsgi_opt_load_yml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -366,6 +376,10 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"legion-setup", required_argument, 0, "action to call on legion setup", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
|
||||
{"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0},
|
||||
{"legion-scroll-list-max-size", required_argument, 0, "set max size of legion scroll list buffer", uwsgi_opt_set_64bit, &uwsgi.legion_scroll_list_max_size, 0},
|
||||
{"subscriptions-sign-check", required_argument, 0, "set digest algorithm and certificate directory for secured subscription system", uwsgi_opt_scd, NULL, UWSGI_OPT_MASTER},
|
||||
{"subscriptions-sign-check-tolerance", required_argument, 0, "set the maximum tolerance (in seconds) of clock skew for secured subscription system", uwsgi_opt_set_int, &uwsgi.subscriptions_sign_check_tolerance, UWSGI_OPT_MASTER},
|
||||
#endif
|
||||
@@ -476,7 +490,6 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"die-on-idle", no_argument, 0, "shutdown uWSGI when idle", uwsgi_opt_true, &uwsgi.die_on_idle, 0},
|
||||
{"mount", required_argument, 0, "load application under mountpoint", uwsgi_opt_add_string_list, &uwsgi.mounts, 0},
|
||||
{"worker-mount", required_argument, 0, "load application under mountpoint in the specified worker or after workers spawn", uwsgi_opt_add_string_list, &uwsgi.mounts, 0},
|
||||
{"grunt", no_argument, 0, "enable grunt mode (in-request fork)", uwsgi_opt_true, &uwsgi.grunt, 0},
|
||||
|
||||
{"threads", required_argument, 0, "run each worker in prethreaded mode with the specified number of threads", uwsgi_opt_set_int, &uwsgi.threads, UWSGI_OPT_THREADS},
|
||||
{"thread-stacksize", required_argument, 0, "set threads stacksize", uwsgi_opt_set_int, &uwsgi.threads_stacksize, UWSGI_OPT_THREADS},
|
||||
@@ -602,9 +615,6 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"allowed-modifiers", required_argument, 0, "comma separated list of allowed modifiers", uwsgi_opt_set_str, &uwsgi.allowed_modifiers, 0},
|
||||
{"remap-modifier", required_argument, 0, "remap request modifier from one id to another", uwsgi_opt_set_str, &uwsgi.remap_modifier, 0},
|
||||
|
||||
{"app", required_argument, 0, "*** deprecated ***", uwsgi_opt_deprecated, (void *) "use the more advanced \"mount\" option", 0},
|
||||
{"static-offload-to-thread", required_argument, 0, "*** deprecated ***", uwsgi_opt_deprecated, (void *) "use the more advanced \"offload-threads\" option", 0},
|
||||
|
||||
{"dump-options", no_argument, 0, "dump the full list of available options", uwsgi_opt_true, &uwsgi.dump_options, 0},
|
||||
{"show-config", no_argument, 0, "show the current config reformatted as ini", uwsgi_opt_true, &uwsgi.show_config, 0},
|
||||
{"print", required_argument, 0, "simple print", uwsgi_opt_print, NULL, 0},
|
||||
@@ -971,9 +981,18 @@ void grace_them_all(int signum) {
|
||||
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying)
|
||||
return;
|
||||
|
||||
int i;
|
||||
|
||||
if (uwsgi.lazy) {
|
||||
for (i = 1; i <= uwsgi.numproc; i++) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
uwsgi.status.gracefully_reloading = 1;
|
||||
|
||||
int i;
|
||||
int waitpid_status;
|
||||
|
||||
|
||||
@@ -1006,8 +1025,6 @@ void grace_them_all(int signum) {
|
||||
}
|
||||
}
|
||||
else if (uwsgi.workers[i].pid > 0) {
|
||||
if (uwsgi.lazy)
|
||||
uwsgi.workers[i].destroy = 1;
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
}
|
||||
}
|
||||
@@ -1022,6 +1039,9 @@ void grace_them_all(int signum) {
|
||||
|
||||
void uwsgi_nuclear_blast() {
|
||||
|
||||
// the Emperor (as an example) cannot nuke itself
|
||||
if (uwsgi.disable_nuclear_blast) return;
|
||||
|
||||
if (!uwsgi.workers) {
|
||||
reap_them_all(0);
|
||||
}
|
||||
@@ -1264,6 +1284,7 @@ void signal_pidfile(int sig, char *filename) {
|
||||
else {
|
||||
uwsgi_log("error: invalid pidfile\n");
|
||||
}
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
/*static*/ void uwsgi_command_signal(char *opt) {
|
||||
@@ -1590,10 +1611,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
|
||||
int i;
|
||||
|
||||
#ifdef UNBIT
|
||||
//struct uidsec_struct us;
|
||||
#endif
|
||||
|
||||
struct utsname uuts;
|
||||
|
||||
// signal mask is inherited, and sme process manager could make a real mess...
|
||||
@@ -1695,7 +1712,13 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// count/set the current reload status
|
||||
uwsgi_setup_reload();
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
SYSTEM_INFO si;
|
||||
GetSystemInfo(&si);
|
||||
uwsgi.page_size = si.dwPageSize;
|
||||
#else
|
||||
uwsgi.page_size = getpagesize();
|
||||
#endif
|
||||
uwsgi.binary_path = uwsgi_get_binary_path(argv[0]);
|
||||
|
||||
// ok we can now safely play with argv and environ
|
||||
@@ -1731,6 +1754,7 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// set a couple of 'static' magic vars
|
||||
uwsgi.magic_table['v'] = uwsgi.cwd;
|
||||
uwsgi.magic_table['h'] = uwsgi.hostname;
|
||||
uwsgi.magic_table['V'] = UWSGI_VERSION;
|
||||
|
||||
// you can embed a ini file in the uWSGi binary with default options
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
@@ -1779,12 +1803,14 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
// initial log setup (files and daemonization)
|
||||
uwsgi_setup_log();
|
||||
|
||||
#ifndef __CYGWIN__
|
||||
// enable never-swap mode
|
||||
if (uwsgi.never_swap) {
|
||||
if (mlockall(MCL_CURRENT | MCL_FUTURE)) {
|
||||
uwsgi_error("mlockall()");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (uwsgi.flock2)
|
||||
uwsgi_opt_flock(NULL, uwsgi.flock2, NULL);
|
||||
@@ -3098,6 +3124,18 @@ void uwsgi_init_all_apps() {
|
||||
}
|
||||
}
|
||||
|
||||
usl = uwsgi.exec_post_app;
|
||||
while (usl) {
|
||||
uwsgi_log("running \"%s\" (post app)...\n", usl->value);
|
||||
int ret = uwsgi_run_command_and_wait(NULL, usl->value);
|
||||
if (ret != 0) {
|
||||
uwsgi_log("command \"%s\" exited with non-zero code: %d\n", usl->value, ret);
|
||||
exit(1);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_init_worker_mount_apps() {
|
||||
@@ -3224,6 +3262,12 @@ void uwsgi_opt_set_str(char *opt, char *value, void *key) {
|
||||
*ptr = (char *) value;
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_null(char *opt, char *value, void *key) {
|
||||
char **ptr = (char **) key;
|
||||
*ptr = NULL;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_logger(char *opt, char *value, void *prefix) {
|
||||
|
||||
if (!value)
|
||||
@@ -3457,7 +3501,8 @@ void uwsgi_opt_load_dl(char *opt, char *value, void *none) {
|
||||
|
||||
void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
|
||||
|
||||
char *p = strtok(uwsgi_concat2(value, ""), ",");
|
||||
char *plugins_list = uwsgi_concat2(value, "");
|
||||
char *p = strtok(plugins_list, ",");
|
||||
while (p != NULL) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_debug("loading plugin %s\n", p);
|
||||
@@ -3467,6 +3512,8 @@ void uwsgi_opt_load_plugin(char *opt, char *value, void *none) {
|
||||
}
|
||||
p = strtok(NULL, ",");
|
||||
}
|
||||
free(p);
|
||||
free(plugins_list);
|
||||
}
|
||||
|
||||
void uwsgi_opt_check_static(char *opt, char *value, void *foobar) {
|
||||
@@ -3680,12 +3727,10 @@ void uwsgi_opt_deprecated(char *opt, char *value, void *message) {
|
||||
|
||||
void uwsgi_opt_load(char *opt, char *filename, void *none) {
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
if (uwsgi_endswith(filename, ".ini")) {
|
||||
uwsgi_opt_load_ini(opt, filename, none);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef UWSGI_XML
|
||||
if (uwsgi_endswith(filename, ".xml")) {
|
||||
uwsgi_opt_load_xml(opt, filename, none);
|
||||
@@ -3733,12 +3778,10 @@ void uwsgi_opt_logic(char *opt, char *arg, void *func) {
|
||||
void uwsgi_opt_noop(char *opt, char *foo, void *bar) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
void uwsgi_opt_load_ini(char *opt, char *filename, void *none) {
|
||||
config_magic_table_fill(filename, uwsgi.magic_table);
|
||||
uwsgi_ini_config(filename, uwsgi.magic_table);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_XML
|
||||
void uwsgi_opt_load_xml(char *opt, char *filename, void *none) {
|
||||
@@ -3824,7 +3867,6 @@ void uwsgi_opt_flock(char *opt, char *filename, void *none) {
|
||||
uwsgi_log("uWSGI ERROR: %s is locked by another instance\n", filename);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_flock_wait(char *opt, char *filename, void *none) {
|
||||
@@ -3838,7 +3880,6 @@ void uwsgi_opt_flock_wait(char *opt, char *filename, void *none) {
|
||||
if (uwsgi_fcntl_lock(fd)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// report CFLAGS used for compiling the server
|
||||
|
||||
@@ -6,42 +6,30 @@ extern struct uwsgi_server uwsgi;
|
||||
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
|
||||
|
||||
uint32_t opt_value = 0;
|
||||
ssize_t len;
|
||||
|
||||
if (wsgi_req->uh.pktsize != 0 && wsgi_req->uh.pktsize != 4)
|
||||
if (wsgi_req->uh->pktsize != 0 && wsgi_req->uh->pktsize != 4)
|
||||
return UWSGI_OK;
|
||||
|
||||
// write request
|
||||
if (wsgi_req->uh.pktsize == 4) {
|
||||
if (wsgi_req->uh->pktsize == 4) {
|
||||
memcpy(&opt_value, wsgi_req->buffer, 4);
|
||||
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
|
||||
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
|
||||
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh->modifier2, opt_value);
|
||||
uwsgi.shared->options[wsgi_req->uh->modifier2] = opt_value;
|
||||
|
||||
// ACK
|
||||
wsgi_req->uh.modifier1 = 255;
|
||||
wsgi_req->uh.pktsize = 0;
|
||||
wsgi_req->uh.modifier2 = 1;
|
||||
len = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
wsgi_req->uh->modifier1 = 255;
|
||||
wsgi_req->uh->pktsize = 0;
|
||||
wsgi_req->uh->modifier2 = 1;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
|
||||
}
|
||||
// get request
|
||||
else {
|
||||
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh.modifier2, uwsgi.shared->options[wsgi_req->uh.modifier2]);
|
||||
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh->modifier2, uwsgi.shared->options[wsgi_req->uh->modifier2]);
|
||||
|
||||
wsgi_req->uh.modifier1 = 10;
|
||||
wsgi_req->uh.pktsize = 4;
|
||||
len = write(wsgi_req->poll.fd, wsgi_req, 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
return UWSGI_OK;
|
||||
}
|
||||
len = write(wsgi_req->poll.fd, (char *) &uwsgi.shared->options[wsgi_req->uh.modifier2], 4);
|
||||
if (len != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
|
||||
wsgi_req->uh->modifier1 = 10;
|
||||
wsgi_req->uh->pktsize = 4;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *)wsgi_req->uh , 4);
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) &uwsgi.shared->options[wsgi_req->uh->modifier2], 4);
|
||||
}
|
||||
|
||||
return UWSGI_OK;
|
||||
|
||||
+46
-10
@@ -9,9 +9,10 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct carbon_server_list {
|
||||
char *value; // server address
|
||||
int healthy;
|
||||
int errors;
|
||||
char *hostname;
|
||||
char *port;
|
||||
struct carbon_server_list *next;
|
||||
};
|
||||
|
||||
@@ -33,6 +34,7 @@ struct uwsgi_carbon {
|
||||
char *root_node;
|
||||
char *hostname_dot_replacement;
|
||||
char *hostname;
|
||||
int resolve_hostname;
|
||||
struct uwsgi_stats_pusher *pusher;
|
||||
} u_carbon;
|
||||
|
||||
@@ -46,6 +48,8 @@ static struct uwsgi_option carbon_options[] = {
|
||||
{"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},
|
||||
{"carbon-name-resolve", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{"carbon-resolve-names", no_argument, 0, "allow using hostname as carbon server address (default disabled)", uwsgi_opt_true, &u_carbon.resolve_hostname, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -59,15 +63,32 @@ static void carbon_post_init() {
|
||||
|
||||
while(usl) {
|
||||
struct carbon_server_list *u_server = uwsgi_calloc(sizeof(struct carbon_server_list));
|
||||
u_server->value = usl->value;
|
||||
u_server->healthy = 1;
|
||||
u_server->errors = 0;
|
||||
|
||||
char *p = strtok(usl->value, ":");
|
||||
while (p) {
|
||||
if (!u_server->hostname) {
|
||||
u_server->hostname = uwsgi_str(p);
|
||||
}
|
||||
else if (!u_server->port) {
|
||||
u_server->port = uwsgi_str(p);
|
||||
}
|
||||
else break;
|
||||
p = strtok(NULL, ":");
|
||||
}
|
||||
if (!u_server->hostname || !u_server->port) {
|
||||
uwsgi_log("[carbon] invalid carbon server address (%s)\n", usl->value);
|
||||
usl = usl->next;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (u_carbon.servers_data) {
|
||||
u_server->next = u_carbon.servers_data;
|
||||
}
|
||||
u_carbon.servers_data = u_server;
|
||||
|
||||
uwsgi_log("[carbon] added server %s\n", usl->value);
|
||||
uwsgi_log("[carbon] added server %s:%s\n", u_server->hostname, u_server->port);
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
@@ -80,7 +101,7 @@ static void carbon_post_init() {
|
||||
if (u_carbon.timeout < 1) u_carbon.timeout = 3;
|
||||
if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
|
||||
if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
|
||||
if (!u_carbon.id) {
|
||||
if (!u_carbon.id) {
|
||||
u_carbon.id = uwsgi_str(uwsgi.sockets->name);
|
||||
|
||||
for(i=0;i<(int)strlen(u_carbon.id);i++) {
|
||||
@@ -145,6 +166,8 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
int i;
|
||||
int fd;
|
||||
int wok;
|
||||
char *ip;
|
||||
char *carbon_address = NULL;
|
||||
|
||||
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];
|
||||
@@ -157,31 +180,44 @@ static void carbon_push_stats(int retry_cycle, time_t now) {
|
||||
if (retry_cycle && usl->healthy)
|
||||
// skip healthy servers during retry cycle
|
||||
goto nxt;
|
||||
|
||||
|
||||
if (retry_cycle && usl->healthy == 0)
|
||||
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->value, usl->errors);
|
||||
uwsgi_log("[carbon] Retrying failed server at %s (%d)\n", usl->hostname, usl->errors);
|
||||
|
||||
if (!retry_cycle) {
|
||||
usl->healthy = 1;
|
||||
usl->errors = 0;
|
||||
}
|
||||
|
||||
fd = uwsgi_connect(usl->value, u_carbon.timeout, 0);
|
||||
|
||||
if (u_carbon.resolve_hostname) {
|
||||
ip = uwsgi_resolve_ip(usl->hostname);
|
||||
if (!ip) {
|
||||
uwsgi_log("[carbon] Could not resolve hostname %s\n", usl->hostname);
|
||||
goto nxt;
|
||||
}
|
||||
carbon_address = uwsgi_concat3(ip, ":", usl->port);
|
||||
}
|
||||
else {
|
||||
carbon_address = uwsgi_concat3(usl->hostname, ":", usl->port);
|
||||
}
|
||||
fd = uwsgi_connect(carbon_address, u_carbon.timeout, 0);
|
||||
if (fd < 0) {
|
||||
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", usl->value);
|
||||
uwsgi_log("[carbon] Could not connect to carbon server at %s\n", carbon_address);
|
||||
if (usl->errors < u_carbon.max_retries) {
|
||||
u_carbon.need_retry = 1;
|
||||
u_carbon.next_retry = uwsgi_now() + u_carbon.retry_delay;
|
||||
} else {
|
||||
uwsgi_log("[carbon] Maximum number of retries for %s (%d)\n",
|
||||
usl->value, u_carbon.max_retries);
|
||||
carbon_address, u_carbon.max_retries);
|
||||
usl->healthy = 0;
|
||||
usl->errors = 0;
|
||||
}
|
||||
usl->healthy = 0;
|
||||
usl->errors++;
|
||||
free(carbon_address);
|
||||
goto nxt;
|
||||
}
|
||||
free(carbon_address);
|
||||
// put the socket in non-blocking mode
|
||||
uwsgi_socket_nb(fd);
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int uwsgi_echo_request(struct wsgi_request *wsgi_req) {
|
||||
|
||||
return uwsgi_response_write_body_do(wsgi_req, wsgi_req->buffer, wsgi_req->uh.pktsize);
|
||||
return uwsgi_response_write_body_do(wsgi_req, wsgi_req->buffer, wsgi_req->uh->pktsize);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin echo_plugin = {
|
||||
|
||||
@@ -49,7 +49,7 @@ void uwsgi_imperial_monitor_amqp_event(struct uwsgi_emperor_scanner *ues) {
|
||||
}
|
||||
|
||||
if (msgsize > 0) {
|
||||
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0);
|
||||
emperor_add(ues, amqp_routing_key, uwsgi_now(), config, msgsize, 0, 0, NULL);
|
||||
}
|
||||
|
||||
end0:
|
||||
@@ -88,7 +88,7 @@ end0:
|
||||
emperor_respawn(ui_current, uwsgi_now());
|
||||
}
|
||||
else {
|
||||
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0);
|
||||
emperor_add(ues, config_file, uwsgi_now(), NULL, 0, 0, 0, NULL);
|
||||
}
|
||||
|
||||
free(config_file);
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include "client/dbclient.h"
|
||||
|
||||
@@ -60,7 +60,9 @@ extern "C" void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *ues
|
||||
vassal_gid = tmp_gid;
|
||||
}
|
||||
|
||||
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid);
|
||||
const char *socket_name = p.getStringField("socket");
|
||||
|
||||
uwsgi_emperor_simple_do(ues, (char *) name, (char *) config, vassal_ts/1000, vassal_uid, vassal_gid, (char *) socket_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
void uwsgi_imperial_monitor_mongodb(struct uwsgi_emperor_scanner *);
|
||||
void uwsgi_imperial_monitor_mongodb_init(struct uwsgi_emperor_scanner *);
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import os
|
||||
|
||||
NAME='emperor_mongodb'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
|
||||
|
||||
LIBS = []
|
||||
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
|
||||
LIBS.append('-lmongoclient')
|
||||
LIBS.append('-lboost_thread')
|
||||
LIBS.append('-lboost_filesystem')
|
||||
|
||||
GCC_LIST = ['plugin', 'emperor_mongodb.cc']
|
||||
|
||||
@@ -68,7 +68,11 @@ void uwsgi_imperial_monitor_pg(struct uwsgi_emperor_scanner *ues) {
|
||||
vassal_uid = uwsgi_str_num(q_uid, strlen(q_uid));
|
||||
vassal_gid = uwsgi_str_num(q_gid, strlen(q_gid));
|
||||
}
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid);
|
||||
char *socket_name = NULL;
|
||||
if (PQnfields(res) > 5) {
|
||||
socket_name = PQgetvalue(res, i, 5);
|
||||
}
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_str_num(ts, len), vassal_uid, vassal_gid, socket_name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -64,15 +64,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
int64_t more = 0;
|
||||
size_t more_size = sizeof(more);
|
||||
int i;
|
||||
zmq_msg_t msg[5];
|
||||
zmq_msg_t msg[6];
|
||||
|
||||
zmq_msg_init(&msg[0]);
|
||||
zmq_msg_init(&msg[1]);
|
||||
zmq_msg_init(&msg[2]);
|
||||
zmq_msg_init(&msg[3]);
|
||||
zmq_msg_init(&msg[4]);
|
||||
zmq_msg_init(&msg[5]);
|
||||
|
||||
for(i=0;i<5;i++) {
|
||||
for(i=0;i<6;i++) {
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
zmq_recvmsg(ues->data, &msg[i], ZMQ_DONTWAIT);
|
||||
#else
|
||||
@@ -105,6 +106,11 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
char *ez_gid = NULL;
|
||||
size_t ez_gid_len = 0;
|
||||
|
||||
char *ez_socket_name = NULL;
|
||||
size_t ez_socket_name_len = 0;
|
||||
|
||||
char *socket_name = NULL;
|
||||
|
||||
// config
|
||||
if (i > 1) {
|
||||
ez_config = zmq_msg_data(&msg[2]);
|
||||
@@ -123,6 +129,12 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
ez_gid_len = zmq_msg_size(&msg[4]);
|
||||
}
|
||||
|
||||
// gid
|
||||
if (i > 4) {
|
||||
ez_socket_name = zmq_msg_data(&msg[5]);
|
||||
ez_socket_name_len = zmq_msg_size(&msg[5]);
|
||||
}
|
||||
|
||||
char *name = uwsgi_concat2n(ez_name, ez_name_len, "", 0);
|
||||
|
||||
// ok let's start checking commands
|
||||
@@ -142,10 +154,16 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
vassal_gid = uwsgi_str_num(ez_gid, ez_gid_len);
|
||||
}
|
||||
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid);
|
||||
if (ez_socket_name) {
|
||||
socket_name = uwsgi_concat2n(ez_socket_name, ez_socket_name_len, "", 0);
|
||||
}
|
||||
uwsgi_emperor_simple_do(ues, name, config, uwsgi_now(), vassal_uid, vassal_gid, socket_name);
|
||||
if (config) {
|
||||
free(config);
|
||||
}
|
||||
if (socket_name) {
|
||||
free(socket_name);
|
||||
}
|
||||
}
|
||||
// destroy an instance
|
||||
else if (!uwsgi_strncmp(ez_cmd, ez_cmd_len, "destroy", 6)) {
|
||||
@@ -158,7 +176,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
}
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor-zeromq] unkonwn command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
|
||||
uwsgi_log("[emperor-zeromq] unknown command \"%.*s\"\n", (int)ez_cmd_len, ez_cmd);
|
||||
}
|
||||
|
||||
free(name);
|
||||
@@ -168,6 +186,7 @@ static void uwsgi_imperial_monitor_zeromq_cmd(struct uwsgi_emperor_scanner *ues)
|
||||
zmq_msg_close(&msg[2]);
|
||||
zmq_msg_close(&msg[3]);
|
||||
zmq_msg_close(&msg[4]);
|
||||
zmq_msg_close(&msg[5]);
|
||||
}
|
||||
|
||||
// this is the event manager
|
||||
|
||||
+11
-1
@@ -18,6 +18,7 @@ static void uwsgi_opt_setup_gevent(char *opt, char *value, void *null) {
|
||||
|
||||
static struct uwsgi_option gevent_options[] = {
|
||||
{"gevent", required_argument, 0, "a shortcut enabling gevent loop engine with the specified number of async cores and optimal parameters", uwsgi_opt_setup_gevent, NULL, UWSGI_OPT_THREADS},
|
||||
{"gevent-monkey-patch", no_argument, 0, "call gevent.monkey.patch_all() automatically on startup", uwsgi_opt_true, &ugevent.monkey, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -317,6 +318,16 @@ static void gevent_loop() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// call gevent.monkey.patch_all() if requested
|
||||
if (ugevent.monkey) {
|
||||
PyObject *gevent_monkey_dict = get_uwsgi_pydict("gevent.monkey");
|
||||
if (!gevent_monkey_dict) uwsgi_pyexit;
|
||||
PyObject *gevent_monkey_patch_all = PyDict_GetItemString(gevent_monkey_dict, "patch_all");
|
||||
if (!gevent_monkey_patch_all) uwsgi_pyexit;
|
||||
PyObject *ret = python_call(gevent_monkey_patch_all, PyTuple_New(0), 0, NULL);
|
||||
if (!ret) uwsgi_pyexit;
|
||||
}
|
||||
|
||||
ugevent.spawn = PyDict_GetItemString(gevent_dict, "spawn");
|
||||
if (!ugevent.spawn) uwsgi_pyexit;
|
||||
|
||||
@@ -329,7 +340,6 @@ static void gevent_loop() {
|
||||
ugevent.greenlet_switch_args = PyTuple_New(0);
|
||||
Py_INCREF(ugevent.greenlet_switch_args);
|
||||
|
||||
|
||||
PyObject *gevent_get_hub = PyDict_GetItemString(gevent_dict, "get_hub");
|
||||
|
||||
ugevent.hub = python_call(gevent_get_hub, PyTuple_New(0), 0, NULL);
|
||||
|
||||
@@ -52,5 +52,6 @@ struct uwsgi_gevent {
|
||||
PyObject *signal_watcher;
|
||||
PyObject **watchers;
|
||||
int destroy;
|
||||
int monkey;
|
||||
};
|
||||
|
||||
|
||||
+2
-2
@@ -587,6 +587,8 @@ ssize_t http_parse(struct corerouter_peer *main_peer) {
|
||||
size_t len = main_peer->in->pos;
|
||||
char *ptr = main_peer->in->buf;
|
||||
|
||||
hr->rnrn = 0;
|
||||
|
||||
for (j = 0; j < len; j++) {
|
||||
if (*ptr == '\r' && (hr->rnrn == 0 || hr->rnrn == 2)) {
|
||||
hr->rnrn++;
|
||||
@@ -770,8 +772,6 @@ int http_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket
|
||||
|
||||
}
|
||||
|
||||
hr->rnrn = 0;
|
||||
|
||||
hr->port = ugs->port;
|
||||
hr->port_len = ugs->port_len;
|
||||
switch(ugs->mode) {
|
||||
|
||||
@@ -108,3 +108,5 @@ int uwsgi_jvm_object_to_response_body(struct wsgi_request *, jobject);
|
||||
jobject uwsgi_jvm_bytearray(char *, size_t);
|
||||
char *uwsgi_jvm_bytearray2c(jobject);
|
||||
void uwsgi_jvm_release_bytearray(jobject, char *);
|
||||
|
||||
jobject uwsgi_jvm_to_string(jobject);
|
||||
|
||||
@@ -243,6 +243,15 @@ jobject uwsgi_jvm_entryset(jobject o) {
|
||||
return uwsgi_jvm_call_object(o, mid);
|
||||
}
|
||||
|
||||
jobject uwsgi_jvm_to_string(jobject o) {
|
||||
jclass c = uwsgi_jvm_class_from_object(o);
|
||||
if (!c) return NULL;
|
||||
jmethodID mid = uwsgi_jvm_get_method_id_quiet(c, "toString", "()Ljava/lang/String;");
|
||||
uwsgi_jvm_local_unref(c);
|
||||
if (!mid) return NULL;
|
||||
return uwsgi_jvm_call_object(o, mid);
|
||||
}
|
||||
|
||||
int uwsgi_jvm_object_to_response_body(struct wsgi_request *wsgi_req, jobject body) {
|
||||
|
||||
// check for string
|
||||
@@ -297,20 +306,35 @@ int uwsgi_jvm_object_to_response_body(struct wsgi_request *wsgi_req, jobject bod
|
||||
ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len);
|
||||
uwsgi_jvm_release_chars(chunk, c_body);
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
if (ret) goto done;
|
||||
continue;
|
||||
}
|
||||
else if (uwsgi_jvm_object_is_instance(chunk, ujvm.bytearray_class)) {
|
||||
|
||||
if (uwsgi_jvm_object_is_instance(chunk, ujvm.bytearray_class)) {
|
||||
char *c_body = uwsgi_jvm_bytearray2c(chunk);
|
||||
size_t c_body_len = uwsgi_jvm_array_len(chunk);
|
||||
ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len);
|
||||
uwsgi_jvm_release_bytearray(chunk, c_body);
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
if (ret) goto done;
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
uwsgi_log("body iterable item must be java/lang/String or array of bytes!!!\n");
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
goto done;
|
||||
|
||||
jobject str_o = uwsgi_jvm_to_string(chunk);
|
||||
if (str_o) {
|
||||
char *c_body = uwsgi_jvm_str2c(str_o);
|
||||
size_t c_body_len = uwsgi_jvm_strlen(str_o);
|
||||
ret = uwsgi_response_write_body_do(wsgi_req, c_body, c_body_len);
|
||||
uwsgi_jvm_release_chars(str_o, c_body);
|
||||
uwsgi_jvm_local_unref(str_o);
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
if (ret) goto done;
|
||||
continue;
|
||||
}
|
||||
if (ret) goto done;
|
||||
|
||||
uwsgi_log("body iterable item must be java/lang/String or array of bytes!!!\n");
|
||||
uwsgi_jvm_local_unref(chunk);
|
||||
goto done;
|
||||
}
|
||||
done:
|
||||
uwsgi_jvm_local_unref(chunks);
|
||||
@@ -592,11 +616,10 @@ int uwsgi_jvm_consume_input_stream(struct wsgi_request *wsgi_req, size_t chunk,
|
||||
break;
|
||||
}
|
||||
// get the body of the array
|
||||
size_t buf_len = uwsgi_jvm_array_len(byte_buffer);
|
||||
char *buf = (char *) (*ujvm_env)->GetByteArrayElements(ujvm_env, byte_buffer, JNI_FALSE);
|
||||
if (!buf) { ret = -1; break; }
|
||||
//send
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, buf_len)) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, buf, len)) {
|
||||
(*ujvm_env)->ReleaseByteArrayElements(ujvm_env, byte_buffer, (jbyte *) buf, 0);
|
||||
ret = -1; break;
|
||||
}
|
||||
|
||||
@@ -20,6 +20,9 @@ if operating_system == 'darwin':
|
||||
if os.path.exists(jvm):
|
||||
JVM_INCPATH = ["-Wno-deprecated-declarations", "-I%s" % jvm]
|
||||
JVM_LIBPATH = ["-framework JavaVM"]
|
||||
elif operating_system.startswith('cygwin'):
|
||||
JVM_INCPATH = ['-I"/cygdrive/c/Program Files/Java/jdk1.7.0_17/include"', '-I"/cygdrive/c/Program Files/Java/jdk1.7.0_17/include/win32"']
|
||||
JVM_LIBPATH = ['-L"/cygdrive/c/Program Files/Java/jdk1.7.0_17/jre/bin/server"']
|
||||
else:
|
||||
known_jvms = ('/usr/lib/jvm/java-7-openjdk', '/usr/local/openjdk7', '/usr/lib/jvm/java-6-openjdk', '/usr/local/openjdk', '/usr/java', '/usr/lib/jvm/java/')
|
||||
for jvm in known_jvms:
|
||||
@@ -33,15 +36,15 @@ else:
|
||||
JVM_LIBPATH = ["-L%s/jre/lib/%s/server" % (jvm, arch)]
|
||||
break
|
||||
|
||||
try:
|
||||
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
JVM_INCPATH = ['-I"' + os.environ['UWSGICONFIG_JVM_INCPATH'] + '"']
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
JVM_LIBPATH = os.environ['UWSGICONFIG_JVM_LIBPATH']
|
||||
except:
|
||||
pass
|
||||
try:
|
||||
JVM_LIBPATH = ['-L"' + os.environ['UWSGICONFIG_JVM_LIBPATH'] + '"']
|
||||
except:
|
||||
pass
|
||||
|
||||
if not JVM_INCPATH or not JVM_LIBPATH:
|
||||
print("unable to autodetect the JVM path, please specify UWSGICONFIG_JVM_INCPATH and UWSGICONFIG_JVM_LIBPATH environment vars")
|
||||
@@ -66,3 +69,17 @@ def post_build(config):
|
||||
if os.system("cd %s/plugins/jvm ; jar cvf uwsgi.jar *.class" % os.getcwd()) != 0:
|
||||
os._exit(1)
|
||||
print("*** uwsgi.jar available in %s/plugins/jvm/uwsgi.jar ***" % os.getcwd())
|
||||
|
||||
env = os.environ.get('VIRTUAL_ENV')
|
||||
if env:
|
||||
src = "%s/plugins/jvm/uwsgi.jar" % os.getcwd()
|
||||
tgt = "%s/lib/uwsgi.jar" % env
|
||||
shutil.copyfile(src, tgt)
|
||||
print("*** uwsgi.jar had been copied to %s" % tgt)
|
||||
|
||||
plugin = "%s/jvm_plugin.so" % os.getcwd()
|
||||
if os.path.exists(plugin):
|
||||
tgt = "%s/bin/jvm_plugin.so" % env
|
||||
shutil.copyfile(plugin, tgt)
|
||||
print("*** jvm_plugin.so had been copied to %s" % tgt)
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ except:
|
||||
exec(f.read(), up)
|
||||
f.close()
|
||||
|
||||
NAME='ring'
|
||||
NAME='jwsgi'
|
||||
CFLAGS = up['CFLAGS']
|
||||
CFLAGS.append('-I%s' % jvm_path)
|
||||
LDFLAGS = []
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
this is an UDP logger encrypting each packet with the choosen algo, key and iv.
|
||||
|
||||
It is useful in cloud services without persistent storage for which you want to send logs to an external system.
|
||||
|
||||
Syntax: --logger/--req-logger crypto:addr=<udp_address>,algo=<algorithm>,secret=<key>,iv=<iv>,prefix=<prefix>
|
||||
|
||||
example:
|
||||
|
||||
uwsgi --plugin logcrypto --logger crypto:addr=127.0.0.1:1717,algo=bf-cbc,secret=ciaociao -M -p 4 -s :3031
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_crypto_logger_conf {
|
||||
EVP_CIPHER_CTX *encrypt_ctx;
|
||||
char *addr;
|
||||
char *algo;
|
||||
char *secret;
|
||||
char *iv;
|
||||
char *prefix;
|
||||
size_t prefix_len;
|
||||
};
|
||||
|
||||
static void uwsgi_crypto_logger_setup_encryption(struct uwsgi_crypto_logger_conf *uclc) {
|
||||
|
||||
if (!uwsgi.ssl_initialized) {
|
||||
uwsgi_ssl_init();
|
||||
}
|
||||
|
||||
uclc->encrypt_ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
|
||||
EVP_CIPHER_CTX_init(uclc->encrypt_ctx);
|
||||
|
||||
const EVP_CIPHER *cipher = EVP_get_cipherbyname(uclc->algo);
|
||||
if (!cipher) {
|
||||
uwsgi_log_safe("[uwsgi-logcrypto] unable to find algorithm/cipher\n");
|
||||
exit(1);
|
||||
}
|
||||
int cipher_len = EVP_CIPHER_key_length(cipher);
|
||||
|
||||
size_t s_len = strlen(uclc->secret);
|
||||
if ((unsigned int) cipher_len > s_len) {
|
||||
char *secret_tmp = uwsgi_malloc(cipher_len);
|
||||
memcpy(secret_tmp, uclc->secret, s_len);
|
||||
memset(secret_tmp + s_len, 0, cipher_len - s_len);
|
||||
uclc->secret = secret_tmp;
|
||||
}
|
||||
|
||||
int iv_len = EVP_CIPHER_iv_length(cipher);
|
||||
size_t s_iv_len = 0;
|
||||
if (uclc->iv) {
|
||||
s_iv_len = strlen(uclc->iv);
|
||||
}
|
||||
if ((unsigned int) iv_len > s_iv_len) {
|
||||
char *secret_tmp = uwsgi_malloc(iv_len);
|
||||
memcpy(secret_tmp, uclc->iv, s_iv_len);
|
||||
memset(secret_tmp + s_iv_len, '0', iv_len - s_iv_len);
|
||||
uclc->iv = secret_tmp;
|
||||
}
|
||||
|
||||
if (EVP_EncryptInit_ex(uclc->encrypt_ctx, cipher, NULL, (const unsigned char *) uclc->secret, (const unsigned char *) uclc->iv) <= 0) {
|
||||
uwsgi_error_safe("uwsgi_crypto_logger_setup_encryption()/EVP_EncryptInit_ex()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_crypto_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
struct uwsgi_crypto_logger_conf *uclc = (struct uwsgi_crypto_logger_conf *) ul->data;
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
uclc = uwsgi_calloc(sizeof(struct uwsgi_crypto_logger_conf));
|
||||
|
||||
if (uwsgi_kvlist_parse(ul->arg, strlen(ul->arg), ',', '=',
|
||||
"addr", &uclc->addr,
|
||||
"algo", &uclc->algo,
|
||||
"secret", &uclc->secret,
|
||||
"iv", &uclc->iv,
|
||||
"prefix", &uclc->prefix,
|
||||
NULL)) {
|
||||
uwsgi_log_safe("[uwsgi-logcrypto] unable to parse options\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!uclc->addr || !uclc->algo || !uclc->secret) {
|
||||
uwsgi_log_safe("[uwsgi-logcrypto] you have to specify at least addr,algo and secret options\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (uclc->prefix) {
|
||||
uclc->prefix_len = strlen(uclc->prefix);
|
||||
}
|
||||
|
||||
char *colon = strchr(uclc->addr, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log_safe("[uwsgi-logcrypto] invalid UDP address\n");
|
||||
exit(1);
|
||||
}
|
||||
ul->addr_len = socket_to_in_addr(uclc->addr, colon, 0, &ul->addr.sa_in);
|
||||
|
||||
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (ul->fd < 0) {
|
||||
uwsgi_error_safe("uwsgi_crypto_logger()/socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_crypto_logger_setup_encryption(uclc);
|
||||
|
||||
ul->data = uclc;
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
if (uwsgi_buffer_num64(ub, uwsgi_micros())) goto error;
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
|
||||
if (uclc->prefix) {
|
||||
if (uwsgi_buffer_append(ub, uclc->prefix, uclc->prefix_len)) goto error;
|
||||
if (uwsgi_buffer_append(ub, " ", 1)) goto error;
|
||||
}
|
||||
if (uwsgi_buffer_append(ub, message, len)) goto error;
|
||||
|
||||
// let's encrypt the message
|
||||
unsigned char *encrypted = uwsgi_malloc(ub->pos + EVP_MAX_BLOCK_LENGTH);
|
||||
if (EVP_EncryptInit_ex(uclc->encrypt_ctx, NULL, NULL, NULL, NULL) <= 0) {
|
||||
uwsgi_error_safe("[uwsgi-logcrypto] EVP_EncryptInit_ex()");
|
||||
free(encrypted);
|
||||
goto error;
|
||||
}
|
||||
|
||||
int e_len = 0;
|
||||
if (EVP_EncryptUpdate(uclc->encrypt_ctx, encrypted, &e_len, (unsigned char *) ub->buf, ub->pos) <= 0) {
|
||||
uwsgi_error("[uwsgi-logcrypto] EVP_EncryptUpdate()");
|
||||
free(encrypted);
|
||||
goto error;
|
||||
}
|
||||
|
||||
int tmplen = 0;
|
||||
if (EVP_EncryptFinal_ex(uclc->encrypt_ctx, encrypted + e_len, &tmplen) <= 0) {
|
||||
uwsgi_error("[uwsgi-logcrypto] EVP_EncryptFinal_ex()");
|
||||
free(encrypted);
|
||||
goto error;
|
||||
}
|
||||
|
||||
uwsgi_buffer_destroy(ub);
|
||||
|
||||
ssize_t rlen = sendto(ul->fd, encrypted, e_len + tmplen, 0, (struct sockaddr *) &ul->addr.sa_in, ul->addr_len);
|
||||
free(encrypted);
|
||||
return rlen;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
static void uwsgi_logcrypto_register() {
|
||||
uwsgi_register_logger("crypto", uwsgi_crypto_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logcrypto_plugin = {
|
||||
|
||||
.name = "logcrypto",
|
||||
.on_load = uwsgi_logcrypto_register,
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
NAME='logcrypto'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['logcrypto']
|
||||
@@ -0,0 +1,9 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include "client/dbclient.h"
|
||||
|
||||
extern "C" int uwsgi_mongodb_version() {
|
||||
// this is only a hack to force the linked to embed libmongoclient.a
|
||||
mongo::DBClientConnection c;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
a fake plugin used for preloading mongodb library when only available as static.
|
||||
|
||||
*/
|
||||
|
||||
int uwsgi_mongodb_version(void);
|
||||
|
||||
struct uwsgi_plugin mongodb_plugin = {
|
||||
.name = "mongodb",
|
||||
.init = uwsgi_mongodb_version,
|
||||
};
|
||||
@@ -0,0 +1,8 @@
|
||||
NAME='mongodb'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
|
||||
|
||||
GCC_LIST = ['plugin', 'foobar.cc']
|
||||
|
||||
+104
-7
@@ -48,6 +48,7 @@ struct uwsgi_mono {
|
||||
char *assembly_name ;
|
||||
|
||||
struct uwsgi_string_list *key;
|
||||
struct uwsgi_string_list *index;
|
||||
|
||||
// GC frequency
|
||||
uint64_t gc_freq;
|
||||
@@ -61,6 +62,10 @@ struct uwsgi_mono {
|
||||
MonoClass *application_class;
|
||||
MonoClass *api_class;
|
||||
|
||||
MonoClass *byte_class;
|
||||
|
||||
MonoClassField *filepath;
|
||||
|
||||
// thunk
|
||||
void (*process_request)(MonoObject *, MonoException **);
|
||||
|
||||
@@ -78,15 +83,53 @@ struct uwsgi_option uwsgi_mono_options[] = {
|
||||
{"mono-config", required_argument, 0, "set the Mono config file", uwsgi_opt_set_str, &umono.config, 0},
|
||||
{"mono-assembly", required_argument, 0, "load the specified main assembly (default: uwsgi.dll)", uwsgi_opt_set_str, &umono.assembly_name, 0},
|
||||
{"mono-exec", required_argument, 0, "exec the specified assembly just before app loading", uwsgi_opt_add_string_list, &umono.exec, 0},
|
||||
{"mono-index", required_argument, 0, "add an asp.net index file", uwsgi_opt_add_string_list, &umono.index, 0},
|
||||
};
|
||||
|
||||
static MonoString *uwsgi_mono_method_GetFilePath(MonoObject *this) {
|
||||
MonoString *ret = NULL;
|
||||
// cache it !!!
|
||||
MonoObject *filepath = mono_field_get_value_object(mono_domain_get(), umono.filepath, this);
|
||||
if (filepath) {
|
||||
return (MonoString *) filepath;
|
||||
}
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
return mono_string_new_len(mono_domain_get(), wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
struct uwsgi_app *app = &uwsgi_apps[wsgi_req->app_id];
|
||||
char *path = uwsgi_concat3n(app->interpreter, strlen(app->interpreter), "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
size_t path_len = strlen(app->interpreter) + 1 + wsgi_req->path_info_len;
|
||||
|
||||
if (!uwsgi_file_exists(path)) {
|
||||
free(path);
|
||||
goto simple;
|
||||
}
|
||||
|
||||
if (uwsgi_is_dir(path)) {
|
||||
struct uwsgi_string_list *usl = umono.index;
|
||||
while(usl) {
|
||||
char *index = uwsgi_concat3n(path, path_len, "/", 1 , usl->value, usl->len);
|
||||
if (uwsgi_file_exists(index)) {
|
||||
ret = mono_string_new(mono_domain_get(), index + strlen(app->interpreter));
|
||||
free(path);
|
||||
free(index);
|
||||
mono_field_set_value(this, umono.filepath, ret);
|
||||
return ret;
|
||||
}
|
||||
free(index);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
free(path);
|
||||
simple:
|
||||
ret = mono_string_new_len(mono_domain_get(), wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
mono_field_set_value(this, umono.filepath, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static MonoString *uwsgi_mono_method_GetUriPath(MonoObject *this) {
|
||||
return uwsgi_mono_method_GetFilePath(this);
|
||||
}
|
||||
|
||||
static MonoString *uwsgi_mono_method_MapPath(MonoObject *this, MonoString *virtualPath) {
|
||||
// first we need to get the physical path and append the virtualPath to it
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
struct uwsgi_app *app = &uwsgi_apps[wsgi_req->app_id];
|
||||
char *path = uwsgi_concat3n(app->interpreter, strlen(app->interpreter), "/", 1, mono_string_to_utf8(virtualPath), mono_string_length(virtualPath));
|
||||
@@ -115,11 +158,6 @@ static MonoString *uwsgi_mono_method_GetHttpVersion(MonoObject *this) {
|
||||
return mono_string_new_len(mono_domain_get(), wsgi_req->protocol, wsgi_req->protocol_len);
|
||||
}
|
||||
|
||||
static MonoString *uwsgi_mono_method_GetUriPath(MonoObject *this) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
return mono_string_new_len(mono_domain_get(), wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
|
||||
static MonoString *uwsgi_mono_method_GetRemoteAddress(MonoObject *this) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
return mono_string_new_len(mono_domain_get(), wsgi_req->remote_addr, wsgi_req->remote_addr_len);
|
||||
@@ -221,6 +259,26 @@ static int uwsgi_mono_method_api_WorkerId() {
|
||||
return uwsgi.mywid;
|
||||
}
|
||||
|
||||
static MonoArray *uwsgi_mono_method_api_CacheGet(MonoString *key, MonoString *cache) {
|
||||
char *c_key = mono_string_to_utf8(key);
|
||||
uint16_t c_keylen = mono_string_length(key);
|
||||
char *c_cache = NULL;
|
||||
if (cache) {
|
||||
c_cache = mono_string_to_utf8(cache);
|
||||
}
|
||||
uint64_t vallen = 0 ;
|
||||
char *value = uwsgi_cache_magic_get(c_key, c_keylen, &vallen, c_cache);
|
||||
if (value) {
|
||||
MonoArray *ret = mono_array_new(mono_domain_get(), umono.byte_class, vallen);
|
||||
char *buf = mono_array_addr(ret, char, 0);
|
||||
memcpy(buf, value, vallen);
|
||||
free(value);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void uwsgi_mono_add_internal_calls() {
|
||||
// uWSGIRequest
|
||||
mono_add_internal_call("uwsgi.uWSGIRequest::SendResponseFromMemory", uwsgi_mono_method_SendResponseFromMemory);
|
||||
@@ -246,6 +304,7 @@ static void uwsgi_mono_add_internal_calls() {
|
||||
mono_add_internal_call("uwsgi.api::Signal", uwsgi_mono_method_api_Signal);
|
||||
mono_add_internal_call("uwsgi.api::WorkerId", uwsgi_mono_method_api_WorkerId);
|
||||
mono_add_internal_call("uwsgi.api::RegisterSignal", uwsgi_mono_method_api_RegisterSignal);
|
||||
mono_add_internal_call("uwsgi.api::CacheGet", uwsgi_mono_method_api_CacheGet);
|
||||
}
|
||||
|
||||
static int uwsgi_mono_init() {
|
||||
@@ -280,6 +339,16 @@ static void uwsgi_mono_create_jit() {
|
||||
uwsgi_log("Mono JIT initialized on worker %d with version %s\n", uwsgi.mywid, umono.version);
|
||||
|
||||
MonoAssembly *assembly = mono_domain_assembly_open(umono.main_domain, umono.assembly_name);
|
||||
if (!assembly) {
|
||||
uwsgi_log("%s not found trying in global gac...\n", umono.assembly_name);
|
||||
assembly = mono_assembly_load_with_partial_name(umono.assembly_name, NULL);
|
||||
if (!assembly) {
|
||||
if (!strcmp("uwsgi.dll", umono.assembly_name)) {
|
||||
assembly = mono_assembly_load_with_partial_name("uwsgi", NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!assembly) {
|
||||
uwsgi_log("unable to load \"%s\" in the Mono domain\n", umono.assembly_name);
|
||||
exit(1);
|
||||
@@ -298,6 +367,23 @@ static void uwsgi_mono_create_jit() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
umono.byte_class = mono_class_from_name(mono_get_corlib(), "System", "Byte");
|
||||
if (!umono.byte_class) {
|
||||
uwsgi_log("unable to get reference to class System.Byte\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
MonoClass *urequest = mono_class_from_name(image, "uwsgi", "uWSGIRequest");
|
||||
if (!urequest) {
|
||||
uwsgi_log("unable to get reference to class uwsgi.uWSGIRequest\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
umono.filepath = mono_class_get_field_from_name(urequest, "filepath");
|
||||
if (!umono.filepath) {
|
||||
uwsgi_log("unable to get reference to field uwsgi.uWSGIRequest.filepath\n");
|
||||
}
|
||||
|
||||
umono.api_class = mono_class_from_name(image, "uwsgi", "api");
|
||||
if (!umono.api_class) {
|
||||
uwsgi_log("unable to get reference to class uwsgi.api\n");
|
||||
@@ -484,6 +570,17 @@ static int uwsgi_mono_request(struct wsgi_request *wsgi_req) {
|
||||
struct uwsgi_app *app = &uwsgi_apps[wsgi_req->app_id];
|
||||
app->requests++;
|
||||
|
||||
// check for directory without slash
|
||||
char *path = uwsgi_concat3n(app->interpreter, strlen(app->interpreter), "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
size_t path_len = strlen(app->interpreter) + 1 + wsgi_req->path_info_len;
|
||||
|
||||
if (uwsgi_is_dir(path) && path[path_len-1] != '/') {
|
||||
free(path);
|
||||
uwsgi_redirect_to_slash(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
free(path);
|
||||
|
||||
MonoException *exc = NULL;
|
||||
|
||||
umono.process_request(app->callable, &exc);
|
||||
|
||||
@@ -6,6 +6,8 @@ using System.Web.Hosting;
|
||||
using System.Text;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: System.Reflection.AssemblyVersion ("0.0.0.1")]
|
||||
|
||||
namespace uwsgi {
|
||||
|
||||
public delegate void uWSGIHook();
|
||||
@@ -32,10 +34,15 @@ namespace uwsgi {
|
||||
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
extern public static void Signal(int signum);
|
||||
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
extern public static byte[] CacheGet(string key, string cache=null);
|
||||
}
|
||||
|
||||
class uWSGIRequest: HttpWorkerRequest {
|
||||
|
||||
private String filepath = null;
|
||||
|
||||
public override string GetAppPath() {
|
||||
return "/";
|
||||
}
|
||||
@@ -135,6 +142,9 @@ namespace uwsgi {
|
||||
[MethodImplAttribute(MethodImplOptions.InternalCall)]
|
||||
extern public override void SendUnknownResponseHeader (string name, string value);
|
||||
|
||||
public string hack_current_filename() {
|
||||
return filepath;
|
||||
}
|
||||
}
|
||||
|
||||
public class uWSGIApplicationHost: MarshalByRefObject {
|
||||
|
||||
@@ -7,6 +7,8 @@ LIBS = os.popen('pkg-config --libs mono-2').read().rstrip().split()
|
||||
GCC_LIST = ['mono_plugin']
|
||||
|
||||
def post_build(config):
|
||||
if os.system("mcs /target:library /r:System.Web.dll plugins/mono/uwsgi.cs") != 0:
|
||||
if os.system("sn -k plugins/mono/uwsgi.key") != 0:
|
||||
os._exit(1)
|
||||
print("*** uwsgi.dll available in %s/plugins/mono ***" % os.getcwd())
|
||||
if os.system("mcs /target:library /r:System.Web.dll /keyfile:plugins/mono/uwsgi.key plugins/mono/uwsgi.cs") != 0:
|
||||
os._exit(1)
|
||||
print("*** uwsgi.dll available in %s/plugins/mono/uwsgi.dll ***" % os.getcwd())
|
||||
|
||||
@@ -305,7 +305,7 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
|
||||
|
||||
// cache most used values
|
||||
wi->error = PyFile_FromFile(stderr, "wsgi_errors", "w", NULL);
|
||||
Py_INCREF(wi->error);
|
||||
Py_INCREF((PyObject *)wi->error);
|
||||
|
||||
wi->gateway_version = PyTuple_New(2);
|
||||
PyTuple_SetItem(wi->gateway_version, 0, PyInt_FromLong(1));
|
||||
@@ -563,7 +563,9 @@ PyObject *uwsgi_file_loader(void *arg1) {
|
||||
char *callable = up.callable;
|
||||
if (!callable) callable = "application";
|
||||
|
||||
char *py_filename = uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename));
|
||||
char *pythonized_filename = uwsgi_pythonize(filename);
|
||||
char *py_filename = uwsgi_concat2("uwsgi_file_", pythonized_filename);
|
||||
free(pythonized_filename);
|
||||
|
||||
wsgi_file_module = uwsgi_pyimport_by_filename(py_filename, filename);
|
||||
if (!wsgi_file_module) {
|
||||
|
||||
@@ -55,7 +55,6 @@ void uwsgi_opt_pyver(char *opt, char *foo, void *bar) {
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_INI
|
||||
void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
|
||||
|
||||
uwsgi_opt_load_ini(opt, value, NULL);
|
||||
@@ -72,7 +71,6 @@ void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"wsgi-file", required_argument, 0, "load .wsgi file", uwsgi_opt_set_str, &up.file_config, 0},
|
||||
@@ -121,13 +119,13 @@ struct uwsgi_option uwsgi_python_options[] = {
|
||||
{"web3", required_argument, 0, "load a web3 app", uwsgi_opt_set_str, &up.web3, 0},
|
||||
{"pump", required_argument, 0, "load a pump app", uwsgi_opt_set_str, &up.pump, 0},
|
||||
{"wsgi-lite", required_argument, 0, "load a wsgi-lite app", uwsgi_opt_set_str, &up.wsgi_lite, 0},
|
||||
#ifdef UWSGI_INI
|
||||
{"ini-paste", required_argument, 0, "load a paste.deploy config file containing uwsgi section", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"ini-paste-logged", required_argument, 0, "load a paste.deploy config file containing uwsgi section (load loggers too)", uwsgi_opt_ini_paste, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
{"reload-os-env", no_argument, 0, "force reload of os.environ at each request", uwsgi_opt_true, &up.reload_os_env, 0},
|
||||
#ifndef __CYGWIN__
|
||||
#ifndef UWSGI_PYPY
|
||||
{"no-site", no_argument, 0, "do not import site module", uwsgi_opt_true, &Py_NoSiteFlag, 0},
|
||||
#endif
|
||||
#endif
|
||||
{"pyshell", no_argument, 0, "run an interactive python shell in the uWSGI environment", uwsgi_opt_pyshell, NULL, 0},
|
||||
{"pyshell-oneshot", no_argument, 0, "run an interactive python shell in the uWSGI environment (one-shot variant)", uwsgi_opt_pyshell, NULL, 0},
|
||||
|
||||
@@ -335,28 +335,31 @@ shit:
|
||||
if (code_start) {
|
||||
code_end = name_to_symbol_pkg(fullname2, "end");
|
||||
if (code_end) {
|
||||
char *symbolized;
|
||||
PyObject *mod = PyImport_AddModule(fullname);
|
||||
if (!mod) goto clear;
|
||||
PyObject *dict = PyModule_GetDict(mod);
|
||||
if (!dict) goto clear;
|
||||
|
||||
source = uwsgi_concat2n(code_start, code_end-code_start, "", 0);
|
||||
modname = uwsgi_concat3("sym://", symbolize(fullname), "___init___py");
|
||||
symbolized = symbolize(fullname);
|
||||
modname = uwsgi_concat3("sym://", symbolized, "___init___py");
|
||||
|
||||
PyObject *pkgpath = Py_BuildValue("[O]", PyString_FromString(modname));
|
||||
|
||||
PyDict_SetItemString(dict, "__path__", pkgpath);
|
||||
PyDict_SetItemString(dict, "__loader__", self);
|
||||
|
||||
code = Py_CompileString(source, modname, Py_file_input);
|
||||
if (!code) {
|
||||
PyErr_Print();
|
||||
goto shit2;
|
||||
}
|
||||
code = Py_CompileString(source, modname, Py_file_input);
|
||||
if (!code) {
|
||||
PyErr_Print();
|
||||
goto shit2;
|
||||
}
|
||||
mod = PyImport_ExecCodeModuleEx(fullname, code, modname);
|
||||
|
||||
Py_DECREF(code);
|
||||
shit2:
|
||||
free(symbolized);
|
||||
free(source);
|
||||
free(modname);
|
||||
free(fullname2);
|
||||
|
||||
@@ -454,6 +454,57 @@ PyObject *py_uwsgi_i_am_the_lord(PyObject * self, PyObject * args) {
|
||||
Py_INCREF(Py_False);
|
||||
return Py_False;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_lord_scroll(PyObject * self, PyObject * args) {
|
||||
char *legion_name = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:lord_scroll", &legion_name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t rlen = 0;
|
||||
char *buf = uwsgi_legion_lord_scroll(legion_name, &rlen);
|
||||
if (!buf) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *ret = PyString_FromStringAndSize(buf, rlen);
|
||||
free(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void scrolls_items(uint16_t pos, char *key, uint16_t keylen, void *data) {
|
||||
PyObject *list = (PyObject *) data;
|
||||
PyObject *zero = PyString_FromStringAndSize(key, keylen);
|
||||
PyList_Append(list, zero);
|
||||
Py_DECREF(zero);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_scrolls(PyObject * self, PyObject * args) {
|
||||
char *legion_name = NULL;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s:scrolls", &legion_name)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint64_t rlen = 0;
|
||||
char *buf = uwsgi_legion_scrolls(legion_name, &rlen);
|
||||
if (!buf) goto end;
|
||||
PyObject *list = PyList_New(0);
|
||||
if (uwsgi_hooked_parse_array(buf, rlen, scrolls_items, list)) {
|
||||
goto error;
|
||||
}
|
||||
free(buf);
|
||||
return list;
|
||||
error:
|
||||
free(buf);
|
||||
end:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
PyObject *py_uwsgi_register_signal(PyObject * self, PyObject * args) {
|
||||
@@ -717,7 +768,7 @@ static PyObject *py_uwsgi_route(PyObject * self, PyObject * args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int ret = uwsgi_route_api_func(wsgi_req, uwsgi_str(router_name), uwsgi_str(router_args));
|
||||
int ret = uwsgi_route_api_func(wsgi_req, router_name, uwsgi_str(router_args));
|
||||
return PyInt_FromLong(ret);
|
||||
}
|
||||
#endif
|
||||
@@ -2331,63 +2382,6 @@ PyObject *py_uwsgi_parse_file(PyObject * self, PyObject * args) {
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
|
||||
|
||||
pid_t grunt_pid;
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
|
||||
if (uwsgi.grunt) {
|
||||
uwsgi_log("spawning a grunt from worker %d (pid :%d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("grunt support is disabled !!!\n");
|
||||
goto clear;
|
||||
}
|
||||
|
||||
// use a normal fork here
|
||||
grunt_pid = fork();
|
||||
if (grunt_pid < 0) {
|
||||
uwsgi_error("fork()");
|
||||
goto clear;
|
||||
}
|
||||
// now i am a grunt, avoid it making mess
|
||||
else if (grunt_pid == 0) {
|
||||
// it will no more accepts requests
|
||||
uwsgi_close_all_sockets();
|
||||
// create a new session
|
||||
setsid();
|
||||
// exit on SIGPIPE
|
||||
signal(SIGPIPE, (void *) &end_me);
|
||||
// here we create a new worker. Each grunt will race on this datas, so do not rely on them
|
||||
uwsgi.mywid = uwsgi.numproc + 1;
|
||||
uwsgi.mypid = getpid();
|
||||
memset(&uwsgi.workers[uwsgi.mywid], 0, sizeof(struct uwsgi_worker));
|
||||
// this is pratically useless...
|
||||
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
|
||||
// this field will be overwrite after each call
|
||||
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
|
||||
|
||||
// reset the random seed
|
||||
uwsgi_python_reset_random_seed();
|
||||
// TODO
|
||||
// manage thread in grunt processes
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
// close connection on the original worker
|
||||
if (PyTuple_Size(args) == 0) {
|
||||
if (wsgi_req->socket) {
|
||||
wsgi_req->socket->proto_close(wsgi_req);
|
||||
}
|
||||
wsgi_req->fd_closed = 1;
|
||||
}
|
||||
|
||||
clear:
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
static PyMethodDef uwsgi_spooler_methods[] = {
|
||||
#ifdef PYTHREE
|
||||
{"send_to_spooler", (PyCFunction) py_uwsgi_send_spool, METH_VARARGS | METH_KEYWORDS, ""},
|
||||
@@ -2434,7 +2428,6 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"get_logvar", py_uwsgi_get_logvar, METH_VARARGS, ""},
|
||||
{"alarm", py_uwsgi_alarm, METH_VARARGS, ""},
|
||||
{"disconnect", py_uwsgi_disconnect, METH_VARARGS, ""},
|
||||
{"grunt", py_uwsgi_grunt, METH_VARARGS, ""},
|
||||
{"lock", py_uwsgi_lock, METH_VARARGS, ""},
|
||||
{"is_locked", py_uwsgi_is_locked, METH_VARARGS, ""},
|
||||
{"unlock", py_uwsgi_unlock, METH_VARARGS, ""},
|
||||
@@ -2471,6 +2464,8 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"logsize", py_uwsgi_logsize, METH_VARARGS, ""},
|
||||
#ifdef UWSGI_SSL
|
||||
{"i_am_the_lord", py_uwsgi_i_am_the_lord, METH_VARARGS, ""},
|
||||
{"lord_scroll", py_uwsgi_lord_scroll, METH_VARARGS, ""},
|
||||
{"scrolls", py_uwsgi_scrolls, METH_VARARGS, ""},
|
||||
#endif
|
||||
{"async_sleep", py_uwsgi_async_sleep, METH_VARARGS, ""},
|
||||
{"async_connect", py_uwsgi_async_connect, METH_VARARGS, ""},
|
||||
|
||||
+14
-14
@@ -320,7 +320,7 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[],
|
||||
ret = rb_protect(rack_call_rpc_handler, rb_args, &error);
|
||||
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -489,7 +489,7 @@ void uwsgi_rack_preinit_apps() {
|
||||
int error = 0;
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
@@ -519,7 +519,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
error = 0;
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(usl->value), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
@@ -527,7 +527,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
if (ur.rack) {
|
||||
ur.dispatcher = rb_protect(init_rack_app, rb_str_new2(ur.rack), &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
if (ur.dispatcher == Qnil) {
|
||||
@@ -551,7 +551,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
uwsgi_log("loading rails app %s\n", ur.rails);
|
||||
rb_protect( require_rails, 0, &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("rails app %s ready\n", ur.rails);
|
||||
@@ -573,7 +573,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
if (acim_call == Qtrue) {
|
||||
ur.dispatcher = rb_protect(uwsgi_rb_call_new, ac_dispatcher, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -583,7 +583,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
uwsgi_log("non-rack rails version detected...loading thin adapter...\n");
|
||||
rb_protect( require_thin, 0, &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
VALUE thin_rack = rb_const_get(rb_cObject, rb_intern("Rack"));
|
||||
@@ -591,7 +591,7 @@ void uwsgi_rack_init_apps(void) {
|
||||
VALUE thin_rack_adapter_rails = rb_const_get(thin_rack_adapter, rb_intern("Rails"));
|
||||
ur.dispatcher = rb_protect( uwsgi_rb_call_new, thin_rack_adapter_rails, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
@@ -963,7 +963,7 @@ VALUE init_rack_app( VALUE script ) {
|
||||
#endif
|
||||
rb_protect( require_rack, 0, &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
return Qnil;
|
||||
}
|
||||
|
||||
@@ -1038,7 +1038,7 @@ int uwsgi_rack_mule(char *opt) {
|
||||
if (uwsgi_endswith(opt, (char *)".rb")) {
|
||||
rb_protect( uwsgi_require_file, rb_str_new2(opt), &error ) ;
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
@@ -1063,7 +1063,7 @@ void uwsgi_rb_post_fork() {
|
||||
// call the post_fork_hook
|
||||
rb_protect(uwsgi_rb_pfh, 0, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1081,7 +1081,7 @@ int uwsgi_rack_mule_msg(char *message, size_t len) {
|
||||
VALUE arg = rb_str_new(message, len);
|
||||
rb_protect(uwsgi_rb_mmh, arg, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
@@ -1107,7 +1107,7 @@ int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
|
||||
rb_ary_store(args, 1, rbsig);
|
||||
rb_protect(rack_call_signal_handler, args, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
rb_gc();
|
||||
return -1;
|
||||
}
|
||||
@@ -1155,7 +1155,7 @@ int uwsgi_rack_spooler(char *filename, char *buf, uint16_t len, char *body, size
|
||||
|
||||
VALUE ret = rb_protect(uwsgi_rb_do_spooler, spool_dict, &error);
|
||||
if (error) {
|
||||
uwsgi_manage_exception(NULL, 0);
|
||||
uwsgi_ruby_exception_log(NULL);
|
||||
rb_gc();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ static int uwsgi_ring_request(struct wsgi_request *wsgi_req) {
|
||||
// *** REQUEST GENERATION ***
|
||||
|
||||
if (uwsgi_ring_request_item_add_keyword(hm, "request-method", 14, wsgi_req->method, wsgi_req->method_len)) goto end;
|
||||
if (uwsgi_ring_request_item_add(hm, "uri", 3, wsgi_req->uri, wsgi_req->uri_len)) goto end;
|
||||
if (uwsgi_ring_request_item_add(hm, "uri", 3, wsgi_req->path_info, wsgi_req->path_info_len)) goto end;
|
||||
if (uwsgi_ring_request_item_add(hm, "server-name", 11, wsgi_req->host, wsgi_req->host_len)) goto end;
|
||||
|
||||
// server-port is required !!!
|
||||
@@ -450,10 +450,13 @@ static int uwsgi_ring_setup() {
|
||||
}
|
||||
|
||||
char *namespace = uwsgi_str(uring.app);
|
||||
char *colon = strchr(namespace, ':');
|
||||
char *colon = strchr(namespace, '/');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid ring application namespace/handler\n");
|
||||
exit(1);
|
||||
colon = strchr(namespace, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid ring application namespace/handler\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
*colon = 0;
|
||||
uring.handler = uwsgi_jvm_call_object_static(clojure, clojure_var, uwsgi_jvm_str(namespace, 0), uwsgi_jvm_str(colon+1, 0));
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
import os
|
||||
import shutil
|
||||
|
||||
jvm_path = 'plugins/jvm'
|
||||
|
||||
up = {}
|
||||
@@ -14,3 +17,13 @@ CFLAGS.append('-I%s' % jvm_path)
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
GCC_LIST = ['ring_plugin']
|
||||
|
||||
def post_build(config):
|
||||
env = os.environ.get('VIRTUAL_ENV')
|
||||
if env:
|
||||
plugin = "%s/ring_plugin.so" % os.getcwd()
|
||||
if os.path.exists(plugin):
|
||||
tgt = "%s/bin/ring_plugin.so" % env
|
||||
shutil.copyfile(plugin, tgt)
|
||||
print("*** ring_plugin.so had been copied to %s" % tgt)
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#ifdef __linux__
|
||||
#include <crypt.h>
|
||||
#elif defined(__CYGWIN__)
|
||||
#include <crypt.h>
|
||||
pthread_mutex_t ur_basicauth_crypt_mutex;
|
||||
#else
|
||||
pthread_mutex_t ur_basicauth_crypt_mutex;
|
||||
#endif
|
||||
|
||||
@@ -10,25 +10,21 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
syntax:
|
||||
|
||||
route = /^foobar1(.*)/ cache:key=foo$1poo,type=body
|
||||
route = /^foobar1 cache:var=PATH_INFO,type=body
|
||||
route = /^foobar2 cache:var=REQUEST_URI,type=full
|
||||
route = /^foobar3 cache:var=REQUEST_URI,type=body,content_type=text/html
|
||||
route = /^foobar1(.*)/ cache:key=foo$1poo,type=body,content_type=text/html,name=foobar
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_router_cache_conf {
|
||||
|
||||
// the name of the cache
|
||||
char *name;
|
||||
|
||||
char *key;
|
||||
size_t key_len;
|
||||
char *var;
|
||||
|
||||
char *type;
|
||||
|
||||
long var_offset;
|
||||
long var_offset_len;
|
||||
|
||||
char *content_type;
|
||||
char *name;
|
||||
size_t content_type_len;
|
||||
|
||||
// 0 -> full, 1 -> body
|
||||
@@ -41,29 +37,14 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
|
||||
struct uwsgi_router_cache_conf *urcc = (struct uwsgi_router_cache_conf *) ur->data2;
|
||||
|
||||
if (!uwsgi.cache_max_items) return UWSGI_ROUTE_NEXT;
|
||||
|
||||
char *c_k = NULL;
|
||||
uint16_t c_k_len = 0;
|
||||
int k_need_free = 0;
|
||||
|
||||
if (urcc->key) {
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
c_k = uwsgi_regexp_apply_ovec(*subject, *subject_len, urcc->key, urcc->key_len, ur->ovector, ur->ovn);
|
||||
c_k_len = strlen(c_k);
|
||||
k_need_free = 1;
|
||||
}
|
||||
else {
|
||||
char **key = (char **) (((char *) wsgi_req) + urcc->var_offset);
|
||||
uint16_t *keylen = (uint16_t *) (((char *) wsgi_req) + urcc->var_offset_len);
|
||||
c_k = *key;
|
||||
c_k_len = *keylen;
|
||||
}
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urcc->key, urcc->key_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
uint64_t valsize = 0;
|
||||
char *value = uwsgi_cache_magic_get(c_k, c_k_len, &valsize, urcc->name);
|
||||
char *value = uwsgi_cache_magic_get(ub->buf, ub->pos, &valsize, urcc->name);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
if (value) {
|
||||
if (urcc->type_num == 1) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto error;
|
||||
@@ -73,17 +54,14 @@ static int uwsgi_routing_func_cache(struct wsgi_request *wsgi_req, struct uwsgi_
|
||||
// body only
|
||||
uwsgi_response_write_body_do(wsgi_req, value, valsize);
|
||||
free(value);
|
||||
if (k_need_free) free(c_k);
|
||||
if (ur->custom)
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
if (k_need_free) free(c_k);
|
||||
|
||||
return UWSGI_ROUTE_NEXT;
|
||||
error:
|
||||
free(value);
|
||||
if (k_need_free) free(c_k);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
@@ -94,7 +72,6 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
|
||||
struct uwsgi_router_cache_conf *urcc = uwsgi_calloc(sizeof(struct uwsgi_router_cache_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"key", &urcc->key,
|
||||
"var", &urcc->var,
|
||||
"content_type", &urcc->content_type,
|
||||
"name", &urcc->name,
|
||||
"type", &urcc->type, NULL)) {
|
||||
@@ -106,8 +83,8 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
|
||||
urcc->key_len = strlen(urcc->key);
|
||||
}
|
||||
|
||||
if (!urcc->key && !urcc->var) {
|
||||
uwsgi_log("invalid route syntax: you need to specify a cache key or var\n");
|
||||
if (!urcc->key) {
|
||||
uwsgi_log("invalid route syntax: you need to specify a cache key\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -116,21 +93,6 @@ static int uwsgi_router_cache(struct uwsgi_route *ur, char *args) {
|
||||
|
||||
urcc->content_type_len = strlen(urcc->content_type);
|
||||
|
||||
if (urcc->var) {
|
||||
if (!strcmp(urcc->var, "REQUEST_URI")) {
|
||||
urcc->var_offset = offsetof(struct wsgi_request, uri);
|
||||
urcc->var_offset_len = offsetof(struct wsgi_request, uri_len);
|
||||
}
|
||||
else if (!strcmp(urcc->var, "PATH_INFO")) {
|
||||
urcc->var_offset = offsetof(struct wsgi_request, path_info);
|
||||
urcc->var_offset_len = offsetof(struct wsgi_request, path_info_len);
|
||||
}
|
||||
else {
|
||||
urcc->var_offset = offsetof(struct wsgi_request, uri);
|
||||
urcc->var_offset_len = offsetof(struct wsgi_request, uri_len);
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(urcc->type, "body")) {
|
||||
urcc->type_num = 1;
|
||||
}
|
||||
|
||||
@@ -40,10 +40,113 @@ static int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
static int uwsgi_routing_func_rpc(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
|
||||
int ret = -1;
|
||||
// this is the list of args
|
||||
char *argv[UMAX8];
|
||||
// this is the size of each argument
|
||||
uint16_t argvs[UMAX8];
|
||||
// this is a placeholder for tmp uwsgi_buffers
|
||||
struct uwsgi_buffer *ubs[UMAX8];
|
||||
|
||||
char **r_argv = (char **) ur->data2;
|
||||
uint16_t *r_argvs = (uint16_t *) ur->data3;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
uint64_t i;
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
|
||||
if (!ubs[i]) goto end;
|
||||
argv[i] = ubs[i]->buf;
|
||||
argvs[i] = ubs[i]->pos;
|
||||
}
|
||||
|
||||
// ok we now need to check it it is a local call or a remote one
|
||||
char *func = uwsgi_str(ur->data);
|
||||
char *remote = NULL;
|
||||
char *at = strchr(func, '@');
|
||||
if (at) {
|
||||
*at = 0;
|
||||
remote = at+1;
|
||||
}
|
||||
uint16_t size;
|
||||
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
|
||||
free(func);
|
||||
if (!response) goto end;
|
||||
|
||||
ret = UWSGI_ROUTE_BREAK;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {free(response) ; goto end;}
|
||||
if (uwsgi_response_add_content_length(wsgi_req, size)) {free(response) ; goto end;}
|
||||
uwsgi_response_write_body_do(wsgi_req, response, size);
|
||||
free(response);
|
||||
|
||||
end:
|
||||
for(i=0;i<ur->custom;i++) {
|
||||
if (ubs[i] != NULL) {
|
||||
uwsgi_buffer_destroy(ubs[i]);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
ur->data = the func name
|
||||
ur->custom = the number of arguments
|
||||
ur->data2 = the pointer to the args
|
||||
ur->data3 = the pointer to the args sizes
|
||||
*/
|
||||
static int uwsgi_router_rpc(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_rpc;
|
||||
ur->custom = 0;
|
||||
ur->data2 = uwsgi_calloc(sizeof(char *) * UMAX8);
|
||||
ur->data3 = uwsgi_calloc(sizeof(uint16_t) * UMAX8);
|
||||
char *p = strtok(args, " ");
|
||||
while(p) {
|
||||
if (!ur->data) {
|
||||
ur->data = p;
|
||||
}
|
||||
else {
|
||||
if (ur->custom >= UMAX8) {
|
||||
uwsgi_log("unable to register route: maximum number of rpc args reached\n");
|
||||
free(ur->data2);
|
||||
free(ur->data3);
|
||||
return -1;
|
||||
}
|
||||
char **argv = (char **) ur->data2;
|
||||
uint16_t *argvs = (uint16_t *) ur->data3;
|
||||
argv[ur->custom] = p;
|
||||
argvs[ur->custom] = strlen(p);
|
||||
ur->custom++;
|
||||
}
|
||||
p = strtok(NULL, " ");
|
||||
}
|
||||
|
||||
if (!ur->data) {
|
||||
uwsgi_log("unable to register route: you need to specify an rpc function\n");
|
||||
free(ur->data2);
|
||||
free(ur->data3);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void router_rpc_register() {
|
||||
uwsgi_register_router("call", uwsgi_router_rpc);
|
||||
uwsgi_register_router("rpc", uwsgi_router_rpc);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct uwsgi_plugin rpc_plugin = {
|
||||
|
||||
.name = "rpc",
|
||||
.modifier1 = 173,
|
||||
|
||||
.request = uwsgi_rpc_request,
|
||||
#ifdef UWSGI_ROUTING
|
||||
.on_load = router_rpc_register,
|
||||
#endif
|
||||
};
|
||||
|
||||
@@ -20,16 +20,19 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (uspool == NULL) {
|
||||
uwsgi_log("the spooler is inactive !!!...skip\n");
|
||||
uwsgi_send_empty_pkt(wsgi_req->poll.fd, NULL, 255, 0);
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
uh.modifier2 = 0;
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) &uh, 4);
|
||||
return -1;
|
||||
}
|
||||
|
||||
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, wsgi_req->buffer, wsgi_req->uh.pktsize, NULL, 0, NULL, 0);
|
||||
i = spool_request(uspool, spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, wsgi_req->buffer, wsgi_req->uh->pktsize, NULL, 0, NULL, 0);
|
||||
uh.modifier1 = 255;
|
||||
uh.pktsize = 0;
|
||||
if (i > 0) {
|
||||
uh.modifier2 = 1;
|
||||
if (write(wsgi_req->poll.fd, &uh, 4) != 4) {
|
||||
if (uwsgi_response_write_body_do(wsgi_req, (char *) &uh, 4)) {
|
||||
uwsgi_log("disconnected client, remove spool file.\n");
|
||||
/* client disconnect, remove spool file */
|
||||
if (unlink(spool_filename)) {
|
||||
@@ -43,10 +46,7 @@ int uwsgi_request_spooler(struct wsgi_request *wsgi_req) {
|
||||
else {
|
||||
/* announce a failed spool request */
|
||||
uh.modifier2 = 0;
|
||||
i = write(wsgi_req->poll.fd, &uh, 4);
|
||||
if (i != 4) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) &uh, 4);
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
void stats_pusher_mongodb(struct uwsgi_stats_pusher_instance *, time_t, char *, size_t);
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include "client/dbclient.h"
|
||||
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import os
|
||||
|
||||
NAME='stats_pusher_mongodb'
|
||||
|
||||
CFLAGS = ['-I/usr/include/mongo','-I/usr/local/include/mongo']
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lmongoclient', '-lboost_thread','-lboost_filesystem']
|
||||
|
||||
LIBS = []
|
||||
if not 'UWSGI_MONGODB_NOLIB' in os.environ:
|
||||
LIBS.append('-lmongoclient')
|
||||
LIBS.append('-lboost_thread')
|
||||
LIBS.append('-lboost_filesystem')
|
||||
|
||||
GCC_LIST = ['plugin', 'stats_pusher_mongodb.cc']
|
||||
|
||||
@@ -0,0 +1,137 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
/*
|
||||
|
||||
this is a stats pusher plugin for the statsd server:
|
||||
|
||||
--stats-push statsd:address[,prefix]
|
||||
|
||||
example:
|
||||
|
||||
--stats-push statsd:127.0.0.1:8125,myinstance
|
||||
|
||||
it is pretty minimal, but will be extended after the 2.0 metric subsystem will be released
|
||||
|
||||
*/
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
// configuration of a statsd node
|
||||
struct statsd_node {
|
||||
int fd;
|
||||
union uwsgi_sockaddr addr;
|
||||
socklen_t addr_len;
|
||||
char *prefix;
|
||||
uint16_t prefix_len;
|
||||
};
|
||||
|
||||
static int statsd_send_worker_gauge(struct uwsgi_buffer *ub, struct uwsgi_stats_pusher_instance *uspi, int wid, char *metric, uint16_t metric_len, int64_t value) {
|
||||
struct statsd_node *sn = (struct statsd_node *) uspi->data;
|
||||
// reset the buffer
|
||||
ub->pos = 0;
|
||||
if (uwsgi_buffer_append(ub, sn->prefix, sn->prefix_len)) return -1;
|
||||
if (uwsgi_buffer_append(ub, ".worker", 7)) return -1;
|
||||
if (uwsgi_buffer_num64(ub, wid)) return -1;
|
||||
if (uwsgi_buffer_append(ub, ".", 1)) return -1;
|
||||
if (uwsgi_buffer_append(ub, metric, metric_len)) return -1;
|
||||
if (uwsgi_buffer_append(ub, ":", 1)) return -1;
|
||||
if (uwsgi_buffer_num64(ub, value)) return -1;
|
||||
if (uwsgi_buffer_append(ub, "|g", 2)) return -1;
|
||||
|
||||
if (sendto(sn->fd, ub->buf, ub->pos, 0, (struct sockaddr *) &sn->addr.sa_in, sn->addr_len) < 0) {
|
||||
uwsgi_error("stats_pusher_statsd()/sendto()");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int statsd_send_core_gauge(struct uwsgi_buffer *ub, struct uwsgi_stats_pusher_instance *uspi, int wid, int coreid, char *metric, uint16_t metric_len, int64_t value) {
|
||||
struct statsd_node *sn = (struct statsd_node *) uspi->data;
|
||||
// reset the buffer
|
||||
ub->pos = 0;
|
||||
if (uwsgi_buffer_append(ub, sn->prefix, sn->prefix_len)) return -1;
|
||||
if (uwsgi_buffer_append(ub, ".worker", 7)) return -1;
|
||||
if (uwsgi_buffer_num64(ub, wid)) return -1;
|
||||
if (uwsgi_buffer_append(ub, ".core", 5)) return -1;
|
||||
if (uwsgi_buffer_num64(ub, coreid)) return -1;
|
||||
if (uwsgi_buffer_append(ub, ".", 1)) return -1;
|
||||
if (uwsgi_buffer_append(ub, metric, metric_len)) return -1;
|
||||
if (uwsgi_buffer_append(ub, ":", 1)) return -1;
|
||||
if (uwsgi_buffer_num64(ub, value)) return -1;
|
||||
if (uwsgi_buffer_append(ub, "|g", 2)) return -1;
|
||||
|
||||
if (sendto(sn->fd, ub->buf, ub->pos, 0, (struct sockaddr *) &sn->addr.sa_in, sn->addr_len) < 0) {
|
||||
uwsgi_error("stats_pusher_statsd()/sendto()");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void stats_pusher_statsd(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {
|
||||
|
||||
if (!uspi->configured) {
|
||||
struct statsd_node *sn = uwsgi_calloc(sizeof(struct statsd_node));
|
||||
char *comma = strchr(uspi->arg, ',');
|
||||
if (comma) {
|
||||
sn->prefix = comma+1;
|
||||
sn->prefix_len = strlen(sn->prefix);
|
||||
*comma = 0;
|
||||
}
|
||||
else {
|
||||
sn->prefix = "uwsgi";
|
||||
sn->prefix_len = 5;
|
||||
}
|
||||
|
||||
char *colon = strchr(uspi->arg, ':');
|
||||
if (!colon) {
|
||||
uwsgi_log("invalid statsd address %s\n", uspi->arg);
|
||||
if (comma) *comma = ',';
|
||||
free(sn);
|
||||
return;
|
||||
}
|
||||
sn->addr_len = socket_to_in_addr(uspi->arg, colon, 0, &sn->addr.sa_in);
|
||||
|
||||
sn->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if (sn->fd < 0) {
|
||||
uwsgi_error("stats_pusher_statsd()/socket()");
|
||||
if (comma) *comma = ',';
|
||||
free(sn);
|
||||
return;
|
||||
}
|
||||
uwsgi_socket_nb(sn->fd);
|
||||
if (comma) *comma = ',';
|
||||
uspi->data = sn;
|
||||
uspi->configured = 1;
|
||||
}
|
||||
|
||||
// we use the same buffer for all of the packets
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
|
||||
int i, j;
|
||||
// send workers metrics
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
if (statsd_send_worker_gauge(ub, uspi, i, "requests", 8, uwsgi.workers[i].requests)) goto end;
|
||||
for(j=0;j<uwsgi.cores;j++) {
|
||||
if (statsd_send_core_gauge(ub, uspi, i, j, "exceptions", 10, uwsgi.workers[i].cores[j].exceptions)) goto end;
|
||||
if (statsd_send_core_gauge(ub, uspi, i, j, "requests", 8, uwsgi.workers[i].cores[j].requests)) goto end;
|
||||
if (statsd_send_core_gauge(ub, uspi, i, j, "routed_requests", 15, uwsgi.workers[i].cores[j].routed_requests)) goto end;
|
||||
if (statsd_send_core_gauge(ub, uspi, i, j, "static_requests", 15, uwsgi.workers[i].cores[j].static_requests)) goto end;
|
||||
if (statsd_send_core_gauge(ub, uspi, i, j, "offloaded_requests", 18, uwsgi.workers[i].cores[j].offloaded_requests)) goto end;
|
||||
}
|
||||
}
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
}
|
||||
|
||||
static void stats_pusher_statsd_init(void) {
|
||||
struct uwsgi_stats_pusher *usp = uwsgi_register_stats_pusher("statsd", stats_pusher_statsd);
|
||||
// we use a custom format not the JSON one
|
||||
usp->raw = 1;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin stats_pusher_statsd_plugin = {
|
||||
|
||||
.name = "stats_pusher_statsd",
|
||||
.on_load = stats_pusher_statsd_init,
|
||||
};
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
NAME='stats_pusher_statsd'
|
||||
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['plugin']
|
||||
@@ -0,0 +1,8 @@
|
||||
import os
|
||||
|
||||
NAME='xslt'
|
||||
CFLAGS = os.popen('xslt-config --cflags').read().rstrip().split()
|
||||
LDFLAGS = os.popen('xslt-config --libs').read().rstrip().split()
|
||||
LIBS = []
|
||||
|
||||
GCC_LIST = ['xslt']
|
||||
@@ -0,0 +1,406 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#include <libxslt/xsltutils.h>
|
||||
#include <libxslt/transform.h>
|
||||
|
||||
/*
|
||||
|
||||
XSLT request plugin
|
||||
|
||||
it takes an XML file as input (taken from DOCUMENT_ROOT + PATH_INFO by default)
|
||||
it search for an XSLT stylesheet (by default in DOCUMENT_ROOT + PATH_INFO - ext + .xsl|.xslt)
|
||||
it applies params (by default taken from the QUERY_STRING)
|
||||
|
||||
XSLT routing instruction
|
||||
|
||||
xslt:doc=<path1>,stylesheet=<path2>,params=<params>
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_xslt_config {
|
||||
struct uwsgi_string_list *docroot;
|
||||
struct uwsgi_string_list *ext;
|
||||
struct uwsgi_string_list *var;
|
||||
struct uwsgi_string_list *stylesheet;
|
||||
char *content_type;
|
||||
uint16_t content_type_len;
|
||||
} uxslt;
|
||||
|
||||
struct uwsgi_router_xslt_conf {
|
||||
char *doc;
|
||||
uint16_t doc_len;
|
||||
char *stylesheet;
|
||||
uint16_t stylesheet_len;
|
||||
char *params;
|
||||
uint16_t params_len;
|
||||
char *content_type;
|
||||
uint16_t content_type_len;
|
||||
};
|
||||
|
||||
struct uwsgi_option uwsgi_xslt_options[] = {
|
||||
{"xslt-docroot", required_argument, 0, "add a document_root for xslt processing", uwsgi_opt_add_string_list, &uxslt.docroot, 0},
|
||||
{"xslt-ext", required_argument, 0, "search for xslt stylesheets with the specified extension", uwsgi_opt_add_string_list, &uxslt.ext, 0},
|
||||
{"xslt-var", required_argument, 0, "get the xslt stylesheet path from the specified request var", uwsgi_opt_add_string_list, &uxslt.var, 0},
|
||||
{"xslt-stylesheet", required_argument, 0, "if no xslt stylesheet file can be found, use the specified one", uwsgi_opt_add_string_list, &uxslt.stylesheet, 0},
|
||||
{"xslt-content-type", required_argument, 0, "set the content-type for the xslt rsult (default: text/html)", uwsgi_opt_set_str, &uxslt.content_type, 0},
|
||||
{NULL, 0, 0, NULL, NULL, NULL, 0},
|
||||
};
|
||||
|
||||
static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char *params, int *rlen) {
|
||||
|
||||
char **vparams = NULL;
|
||||
char *tmp_params = NULL;
|
||||
uint16_t count = 0;
|
||||
if (params) {
|
||||
// first count the number of items
|
||||
size_t i;
|
||||
size_t params_len = strlen(params);
|
||||
for(i=0;i<params_len;i++) {
|
||||
if (params[i] == '=') {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
vparams = uwsgi_calloc( sizeof(char *) * ((count * 2) + 1));
|
||||
tmp_params = uwsgi_str(params);
|
||||
char *p = strtok(tmp_params, "&");
|
||||
int pos = 0;
|
||||
while(p) {
|
||||
char *equal = strchr(p, '=');
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
vparams[pos] = p; pos++;
|
||||
vparams[pos] = uwsgi_concat3("\"", equal+1, "\""); pos++;
|
||||
}
|
||||
p = strtok(NULL, "&");
|
||||
}
|
||||
}
|
||||
|
||||
// we reset them every time to avoid collision with other xml engines
|
||||
xmlSubstituteEntitiesDefault(1);
|
||||
xmlLoadExtDtdDefaultValue = 1;
|
||||
|
||||
xmlDocPtr doc = xmlParseFile(xmlfile);
|
||||
if (!doc) {
|
||||
if (vparams) {
|
||||
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
|
||||
free(tmp_params);
|
||||
free(vparams);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xsltStylesheetPtr ss = xsltParseStylesheetFile((const xmlChar *) xsltfile);
|
||||
if (!ss) {
|
||||
xmlFreeDoc(doc);
|
||||
if (vparams) {
|
||||
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
|
||||
free(tmp_params);
|
||||
free(vparams);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xmlDocPtr res = xsltApplyStylesheet(ss, doc, (const char **) vparams);
|
||||
if (!res) {
|
||||
xsltFreeStylesheet(ss);
|
||||
xmlFreeDoc(doc);
|
||||
if (vparams) {
|
||||
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
|
||||
free(tmp_params);
|
||||
free(vparams);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
xmlChar *output;
|
||||
int ret = xsltSaveResultToString(&output, rlen, res, ss);
|
||||
xsltFreeStylesheet(ss);
|
||||
xmlFreeDoc(res);
|
||||
xmlFreeDoc(doc);
|
||||
if (vparams) {
|
||||
int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
|
||||
free(tmp_params);
|
||||
free(vparams);
|
||||
}
|
||||
if (ret < 0) return NULL;
|
||||
return (char *) output;
|
||||
}
|
||||
|
||||
static int uwsgi_request_xslt(struct wsgi_request *wsgi_req) {
|
||||
|
||||
char *xmlfile = NULL;
|
||||
char *output = NULL;
|
||||
int output_rlen = 0;
|
||||
|
||||
char filename[PATH_MAX+1];
|
||||
size_t filename_len = 0;
|
||||
char stylesheet[PATH_MAX+1];
|
||||
size_t stylesheet_len = 0;
|
||||
|
||||
char *params = NULL;
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// set default values
|
||||
if (!uxslt.content_type_len) {
|
||||
if (!uxslt.content_type) {
|
||||
uxslt.content_type = "text/html";
|
||||
}
|
||||
uxslt.content_type_len = strlen(uxslt.content_type);
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = uxslt.docroot;
|
||||
|
||||
// first check for static docroots
|
||||
if (usl) {
|
||||
while(usl) {
|
||||
xmlfile = uwsgi_concat3n(usl->value, usl->len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
if (uwsgi_is_file(xmlfile)) {
|
||||
break;
|
||||
}
|
||||
free(xmlfile);
|
||||
xmlfile = NULL;
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
// fallback to DOCUMENT_ROOT
|
||||
else {
|
||||
if (wsgi_req->document_root_len == 0) {
|
||||
uwsgi_403(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
xmlfile = uwsgi_concat3n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len);
|
||||
}
|
||||
|
||||
if (!xmlfile) {
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
// we have the full path, check if it is valid
|
||||
if (!uwsgi_expand_path(xmlfile, strlen(xmlfile), filename)) {
|
||||
free(xmlfile);
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
free(xmlfile);
|
||||
|
||||
if (!uwsgi_is_file(filename)) {
|
||||
uwsgi_403(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
filename_len = strlen(filename);
|
||||
|
||||
// now search for the xslt file
|
||||
|
||||
int found = 0;
|
||||
|
||||
// first check for specific vars
|
||||
usl = uxslt.var;
|
||||
while(usl) {
|
||||
uint16_t rlen;
|
||||
char *value = uwsgi_get_var(wsgi_req, usl->value, usl->len, &rlen);
|
||||
if (value) {
|
||||
memcpy(stylesheet, value, rlen);
|
||||
stylesheet[rlen] = 0;
|
||||
stylesheet_len = rlen;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (found) goto apply;
|
||||
|
||||
// then check for custom extensions
|
||||
if (uxslt.ext) {
|
||||
usl = uxslt.ext;
|
||||
while(usl) {
|
||||
char *tmp_path = uwsgi_concat2n(filename, filename_len, usl->value, usl->len);
|
||||
if (uwsgi_is_file(tmp_path)) {
|
||||
stylesheet_len = filename_len + usl->len;
|
||||
memcpy(stylesheet, tmp_path, stylesheet_len);
|
||||
stylesheet[stylesheet_len] = 0;
|
||||
free(tmp_path);
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
free(tmp_path);
|
||||
usl = usl->next;
|
||||
}
|
||||
}
|
||||
// use default extensions .xsl/.xslt
|
||||
else {
|
||||
char *tmp_path = uwsgi_concat2n(filename, filename_len, ".xsl", 4);
|
||||
if (uwsgi_is_file(tmp_path)) {
|
||||
stylesheet_len = filename_len + 4;
|
||||
memcpy(stylesheet, tmp_path, stylesheet_len);
|
||||
stylesheet[stylesheet_len] = 0;
|
||||
free(tmp_path);
|
||||
goto apply;
|
||||
}
|
||||
free(tmp_path);
|
||||
tmp_path = uwsgi_concat2n(filename, filename_len, ".xslt", 5);
|
||||
if (uwsgi_is_file(tmp_path)) {
|
||||
stylesheet_len = filename_len + 5;
|
||||
memcpy(stylesheet, tmp_path, stylesheet_len);
|
||||
stylesheet[stylesheet_len] = 0;
|
||||
found = 1;
|
||||
}
|
||||
free(tmp_path);
|
||||
}
|
||||
|
||||
if (found) goto apply;
|
||||
|
||||
// finally check for static stylesheets
|
||||
usl = uxslt.stylesheet;
|
||||
while(usl) {
|
||||
if (uwsgi_is_file(usl->value)) {
|
||||
memcpy(stylesheet, usl->value, usl->len);
|
||||
stylesheet_len = usl->len;
|
||||
stylesheet[stylesheet_len] = 0;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
usl = usl->next;
|
||||
}
|
||||
|
||||
if (found) goto apply;
|
||||
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
|
||||
apply:
|
||||
if (wsgi_req->query_string_len > 0) {
|
||||
params = uwsgi_concat2n(wsgi_req->query_string, wsgi_req->query_string_len, "", 0);
|
||||
}
|
||||
// we have both the file and the stylesheet, let's run the engine
|
||||
output = uwsgi_xslt_apply(filename, stylesheet, params, &output_rlen);
|
||||
if (params) free(params);
|
||||
if (!output) {
|
||||
uwsgi_500(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
// prepare headers
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {
|
||||
uwsgi_500(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
// content_length
|
||||
if (uwsgi_response_add_content_length(wsgi_req, output_rlen)) {
|
||||
uwsgi_500(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
// content_type
|
||||
if (uwsgi_response_add_content_type(wsgi_req, uxslt.content_type, uxslt.content_type_len)) {
|
||||
uwsgi_500(wsgi_req);
|
||||
goto end;
|
||||
}
|
||||
|
||||
uwsgi_response_write_body_do(wsgi_req, output, output_rlen);
|
||||
|
||||
end:
|
||||
xmlFree(output);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
static void uwsgi_xslt_log(struct wsgi_request *wsgi_req) {
|
||||
log_request(wsgi_req);
|
||||
}
|
||||
|
||||
static int uwsgi_routing_func_xslt(struct wsgi_request *wsgi_req, struct uwsgi_route *ur){
|
||||
|
||||
struct uwsgi_router_xslt_conf *urxc = (struct uwsgi_router_xslt_conf *) ur->data2;
|
||||
|
||||
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
|
||||
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
|
||||
|
||||
struct uwsgi_buffer *ub_doc = NULL;
|
||||
struct uwsgi_buffer *ub_stylesheet = NULL;
|
||||
struct uwsgi_buffer *ub_params = NULL;
|
||||
struct uwsgi_buffer *ub_content_type = NULL;
|
||||
|
||||
ub_doc = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->doc, urxc->doc_len);
|
||||
if (!ub_doc) goto end;
|
||||
ub_stylesheet = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->stylesheet, urxc->stylesheet_len);
|
||||
if (!ub_stylesheet) goto end;
|
||||
|
||||
if (urxc->params) {
|
||||
ub_params = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->params, urxc->params_len);
|
||||
if (!ub_params) goto end;
|
||||
}
|
||||
|
||||
if (urxc->content_type) {
|
||||
ub_content_type = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, urxc->content_type, urxc->content_type_len);
|
||||
if (!ub_content_type) goto end;
|
||||
}
|
||||
|
||||
int rlen;
|
||||
char *output = uwsgi_xslt_apply( ub_doc->buf, ub_stylesheet->buf, ub_params ? ub_params->buf : NULL, &rlen);
|
||||
if (!output) goto end;
|
||||
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) goto end;
|
||||
if (uwsgi_response_add_content_length(wsgi_req, rlen)) goto end;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, urxc->content_type, urxc->content_type_len)) goto end;
|
||||
|
||||
uwsgi_response_write_body_do(wsgi_req, output, rlen);
|
||||
xmlFree(output);
|
||||
|
||||
end:
|
||||
if (ub_doc) uwsgi_buffer_destroy(ub_doc);
|
||||
if (ub_stylesheet) uwsgi_buffer_destroy(ub_stylesheet);
|
||||
if (ub_params) uwsgi_buffer_destroy(ub_params);
|
||||
if (ub_content_type) uwsgi_buffer_destroy(ub_content_type);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_router_xslt(struct uwsgi_route *ur, char *args) {
|
||||
ur->func = uwsgi_routing_func_xslt;
|
||||
ur->data = args;
|
||||
ur->data_len = strlen(args);
|
||||
struct uwsgi_router_xslt_conf *urxc = uwsgi_calloc(sizeof(struct uwsgi_router_xslt_conf));
|
||||
if (uwsgi_kvlist_parse(ur->data, ur->data_len, ',', '=',
|
||||
"doc", &urxc->doc,
|
||||
"stylesheet", &urxc->stylesheet,
|
||||
"content_type", &urxc->content_type,
|
||||
"params", &urxc->params,
|
||||
NULL)) {
|
||||
uwsgi_log("invalid route syntax: %s\n", args);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!urxc->doc && !urxc->stylesheet) {
|
||||
uwsgi_log("invalid route syntax: you need to specify a doc and a stylesheet\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
urxc->doc_len = strlen(urxc->doc);
|
||||
urxc->stylesheet_len = strlen(urxc->stylesheet);
|
||||
|
||||
if (urxc->params) urxc->params_len = strlen(urxc->params);
|
||||
if (!urxc->content_type) urxc->content_type = "text/html";
|
||||
urxc->content_type_len = strlen(urxc->content_type);
|
||||
ur->data2 = urxc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void router_xslt_register() {
|
||||
uwsgi_register_router("xslt", uwsgi_router_xslt);
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_plugin xslt_plugin = {
|
||||
.name = "xslt",
|
||||
.modifier1 = 23,
|
||||
.options = uwsgi_xslt_options,
|
||||
.request = uwsgi_request_xslt,
|
||||
.after_request = uwsgi_xslt_log,
|
||||
.on_load = router_xslt_register,
|
||||
};
|
||||
@@ -104,18 +104,23 @@ struct zergpool_socket *add_zergpool_socket(char *name, char *sockets) {
|
||||
p = strtok(sock_list, ",");
|
||||
while(p) {
|
||||
char *port = strchr(p, ':');
|
||||
char *sockname;
|
||||
if (!port) {
|
||||
z_sock->sockets[pos] = bind_to_unix(p, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
uwsgi_log("zergpool %s bound to UNIX socket %s (fd: %d)\n", name, uwsgi_getsockname(z_sock->sockets[pos]), z_sock->sockets[pos]);
|
||||
sockname = uwsgi_getsockname(z_sock->sockets[pos]);
|
||||
uwsgi_log("zergpool %s bound to UNIX socket %s (fd: %d)\n", name, sockname, z_sock->sockets[pos]);
|
||||
}
|
||||
else {
|
||||
char *gsn = generate_socket_name(p);
|
||||
z_sock->sockets[pos] = bind_to_tcp(gsn, uwsgi.listen_queue, strchr(gsn, ':'));
|
||||
uwsgi_log("zergpool %s bound to TCP socket %s (fd: %d)\n", name, uwsgi_getsockname(z_sock->sockets[pos]), z_sock->sockets[pos]);
|
||||
sockname = uwsgi_getsockname(z_sock->sockets[pos]);
|
||||
uwsgi_log("zergpool %s bound to TCP socket %s (fd: %d)\n", name, sockname, z_sock->sockets[pos]);
|
||||
}
|
||||
pos++;
|
||||
p = strtok(NULL, ",");
|
||||
free(sockname);
|
||||
}
|
||||
free(sock_list);
|
||||
|
||||
return z_sock;
|
||||
}
|
||||
|
||||
+203
-194
@@ -1,32 +1,37 @@
|
||||
#include "../uwsgi.h"
|
||||
/*
|
||||
|
||||
generic ZeroMQ functions + Mongrel2 protocol parser
|
||||
|
||||
*/
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void *uwsgi_zeromq_init() {
|
||||
if (!uwsgi.zmq_context) {
|
||||
uwsgi.zmq_context = zmq_init(1);
|
||||
if (uwsgi.zmq_context == NULL) {
|
||||
uwsgi_error("zmq_init()");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.zmq_context == NULL) {
|
||||
uwsgi_error("zmq_init()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return uwsgi.zmq_context;
|
||||
}
|
||||
|
||||
void uwsgi_zeromq_init_sockets() {
|
||||
|
||||
uwsgi_zeromq_init();
|
||||
uwsgi_zeromq_init();
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
if (!uwsgi_sock->proto_name || strcmp(uwsgi_sock->proto_name, "zmq")) {
|
||||
goto zmq_next;
|
||||
}
|
||||
uwsgi_proto_zeromq_setup(uwsgi_sock);
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (!uwsgi_sock->proto_name || strcmp(uwsgi_sock->proto_name, "zmq")) {
|
||||
goto zmq_next;
|
||||
}
|
||||
uwsgi_proto_zeromq_setup(uwsgi_sock);
|
||||
zmq_next:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -80,6 +85,7 @@ static int uwsgi_mongrel2_json_parse(json_t * root, struct wsgi_request *wsgi_re
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, json_val, strlen(json_val));
|
||||
}
|
||||
|
||||
// pretty easy, we get the file and we map it to wsgi_req->post_file, uWSGI read api will automatically use this
|
||||
if ((json_val = uwsgi_mongrel2_json_get_string(root, "x-mongrel2-upload-done"))) {
|
||||
wsgi_req->post_file = fopen(json_val, "r");
|
||||
if (!wsgi_req->post_file) {
|
||||
@@ -126,12 +132,12 @@ static int uwsgi_mongrel2_json_parse(json_t * root, struct wsgi_request *wsgi_re
|
||||
|
||||
if ((json_val = uwsgi_mongrel2_json_get_string(root, "x-forwarded-for"))) {
|
||||
char *colon = strchr(json_val, ',');
|
||||
if (colon) {
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - json_val);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, json_val, strlen(json_val));
|
||||
}
|
||||
if (colon) {
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - json_val);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, json_val, strlen(json_val));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -228,7 +234,7 @@ static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *
|
||||
if (!uwsgi_strncmp("host", 4, key, keylen)) {
|
||||
char *colon = memchr(val, ':', vallen);
|
||||
if (colon) {
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, vallen - ((colon + 1)-val));
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, vallen - ((colon + 1) - val));
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
|
||||
@@ -250,11 +256,11 @@ static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *
|
||||
else if (!uwsgi_strncmp("x-forwarded-for", 15, key, keylen)) {
|
||||
char *colon = memchr(val, ',', vallen);
|
||||
if (colon) {
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - val);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, val, vallen);
|
||||
}
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - val);
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, val, vallen);
|
||||
}
|
||||
}
|
||||
else if (!uwsgi_strncmp("x-mongrel2-upload-start", 23, key, keylen)) {
|
||||
async_upload += 1;
|
||||
@@ -266,9 +272,9 @@ static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);
|
||||
|
||||
if (query_string == NULL) {
|
||||
// always set QUERY_STRING
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
|
||||
}
|
||||
// always set QUERY_STRING
|
||||
wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
|
||||
}
|
||||
|
||||
// reject uncomplete upload
|
||||
if (async_upload == 1) {
|
||||
@@ -277,6 +283,7 @@ static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *
|
||||
return 0;
|
||||
}
|
||||
|
||||
// fake function, we parse requests in the accept phase
|
||||
int uwsgi_proto_zeromq_parser(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
@@ -284,130 +291,35 @@ int uwsgi_proto_zeromq_parser(struct wsgi_request *wsgi_req) {
|
||||
void uwsgi_proto_zeromq_thread_fixup(struct uwsgi_socket *uwsgi_sock, int async_id) {
|
||||
|
||||
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
|
||||
if (tmp_zmq_pull == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
if (tmp_zmq_pull == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (zmq_connect(tmp_zmq_pull, uwsgi_sock->receiver) < 0) {
|
||||
uwsgi_error("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
if (zmq_connect(tmp_zmq_pull, uwsgi_sock->receiver) < 0) {
|
||||
uwsgi_error("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_setspecific(uwsgi_sock->key, tmp_zmq_pull);
|
||||
|
||||
#ifdef ZMQ_FD
|
||||
if (uwsgi.threads > 1) {
|
||||
size_t zmq_socket_len = sizeof(int);
|
||||
if (zmq_getsockopt(pthread_getspecific(uwsgi_sock->key), ZMQ_FD, &uwsgi_sock->fd_threads[async_id], &zmq_socket_len) < 0) {
|
||||
uwsgi_error("zmq_getsockopt()");
|
||||
exit(1);
|
||||
size_t zmq_socket_len = sizeof(int);
|
||||
if (zmq_getsockopt(pthread_getspecific(uwsgi_sock->key), ZMQ_FD, &uwsgi_sock->fd_threads[async_id], &zmq_socket_len) < 0) {
|
||||
uwsgi_error("zmq_getsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_sock->retry[async_id] = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void uwsgi_proto_zeromq_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
|
||||
char *responder = strchr(uwsgi_sock->name, ',');
|
||||
if (!responder) {
|
||||
uwsgi_log("invalid zeromq address\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_sock->receiver = uwsgi_concat2n(uwsgi_sock->name, responder - uwsgi_sock->name, "", 0);
|
||||
responder++;
|
||||
|
||||
uwsgi_sock->pub = zmq_socket(uwsgi.zmq_context, ZMQ_PUB);
|
||||
if (uwsgi_sock->pub == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
// generate uuid
|
||||
uuid_t uuid_zmq;
|
||||
uuid_generate(uuid_zmq);
|
||||
uuid_unparse(uuid_zmq, uwsgi_sock->uuid);
|
||||
|
||||
if (zmq_setsockopt(uwsgi_sock->pub, ZMQ_IDENTITY, uwsgi_sock->uuid, 36) < 0) {
|
||||
uwsgi_error("zmq_setsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (zmq_connect(uwsgi_sock->pub, responder) < 0) {
|
||||
uwsgi_error("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("zeromq UUID for responder %s on worker %d: %.*s\n", responder, uwsgi.mywid, 36, uwsgi_sock->uuid);
|
||||
|
||||
uwsgi_sock->proto = uwsgi_proto_zeromq_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_zeromq_accept;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_zeromq_close;
|
||||
/*
|
||||
uwsgi_sock->proto_write = uwsgi_proto_zeromq_write;
|
||||
uwsgi_sock->proto_write_header = uwsgi_proto_zeromq_write_header;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_zeromq_sendfile;
|
||||
*/
|
||||
|
||||
uwsgi_sock->proto_thread_fixup = uwsgi_proto_zeromq_thread_fixup;
|
||||
|
||||
uwsgi_sock->edge_trigger = 1;
|
||||
uwsgi_sock->retry = uwsgi_malloc(sizeof(int) * uwsgi.threads);
|
||||
uwsgi_sock->retry[0] = 1;
|
||||
|
||||
// inform loop engine about edge trigger status
|
||||
uwsgi.is_et = 1;
|
||||
|
||||
|
||||
// initialize a lock for multithread usage
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_init(&uwsgi_sock->lock, NULL);
|
||||
}
|
||||
|
||||
// one pull per-thread
|
||||
if (pthread_key_create(&uwsgi_sock->key, NULL)) {
|
||||
uwsgi_error("pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
|
||||
if (tmp_zmq_pull == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
if (zmq_connect(tmp_zmq_pull, uwsgi_sock->receiver) < 0) {
|
||||
uwsgi_error("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_setspecific(uwsgi_sock->key, tmp_zmq_pull);
|
||||
|
||||
#ifdef ZMQ_FD
|
||||
size_t zmq_socket_len = sizeof(int);
|
||||
if (zmq_getsockopt(pthread_getspecific(uwsgi_sock->key), ZMQ_FD, &uwsgi_sock->fd, &zmq_socket_len) < 0) {
|
||||
uwsgi_error("zmq_getsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi_sock->fd_threads = uwsgi_malloc(sizeof(int) * uwsgi.threads);
|
||||
uwsgi_sock->fd_threads[0] = uwsgi_sock->fd;
|
||||
}
|
||||
#else
|
||||
uwsgi_sock->fd = -1;
|
||||
#endif
|
||||
|
||||
uwsgi_sock->bound = 1;
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
uwsgi_sock->recv_flag = ZMQ_DONTWAIT;
|
||||
#else
|
||||
uwsgi_sock->recv_flag = ZMQ_NOBLOCK;
|
||||
#endif
|
||||
// fake function, the bosy is i na file or completely in memory
|
||||
ssize_t uwsgi_proto_zeromq_read_body(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int uwsgi_proto_zeromq_accept(struct wsgi_request *wsgi_req, int fd) {
|
||||
|
||||
zmq_msg_t message;
|
||||
@@ -527,19 +439,14 @@ int uwsgi_proto_zeromq_accept(struct wsgi_request *wsgi_req, int fd) {
|
||||
memcpy((char *) wsgi_req->proto_parser_buf + req_uuid_len + 1 + resp_id_len + 1 + req_id_len, ", ", 2);
|
||||
wsgi_req->proto_parser_pos = (uint64_t) req_uuid_len + 1 + resp_id_len + 1 + req_id_len + 1 + 1;
|
||||
|
||||
// handle post data
|
||||
// handle post data (in memory)
|
||||
if (wsgi_req->post_cl > 0 && !wsgi_req->post_file) {
|
||||
if (uwsgi_netstring(post_data, message_size - (post_data - message_ptr), &message_ptr, &wsgi_req->post_cl)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("post_size: %d\n", wsgi_req->post_cl);
|
||||
#endif
|
||||
wsgi_req->post_file = tmpfile();
|
||||
if (fwrite(message_ptr, wsgi_req->post_cl, 1, wsgi_req->post_file) != 1) {
|
||||
uwsgi_error("fwrite()");
|
||||
zmq_msg_close(&message);
|
||||
goto retry;
|
||||
}
|
||||
rewind(wsgi_req->post_file);
|
||||
wsgi_req->post_read_buf = uwsgi_malloc(wsgi_req->post_cl);
|
||||
memcpy(wsgi_req->post_read_buf, message_ptr, wsgi_req->post_cl);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -563,10 +470,6 @@ retry:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void uwsgi_proto_zeromq_free(void *data, void *hint) {
|
||||
free(data);
|
||||
}
|
||||
|
||||
void uwsgi_proto_zeromq_close(struct wsgi_request *wsgi_req) {
|
||||
zmq_msg_t reply;
|
||||
|
||||
@@ -574,82 +477,188 @@ void uwsgi_proto_zeromq_close(struct wsgi_request *wsgi_req) {
|
||||
if (!wsgi_req->proto_parser_pos)
|
||||
return;
|
||||
|
||||
zmq_msg_init_data(&reply, wsgi_req->proto_parser_buf, wsgi_req->proto_parser_pos, uwsgi_proto_zeromq_free, NULL);
|
||||
if (uwsgi.threads > 1) pthread_mutex_lock(&wsgi_req->socket->lock);
|
||||
// no need to pass a free function (the buffer will be freed during cloe_request)
|
||||
zmq_msg_init_data(&reply, wsgi_req->proto_parser_buf, wsgi_req->proto_parser_pos, NULL, NULL);
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&wsgi_req->socket->lock);
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
if (zmq_sendmsg(wsgi_req->socket->pub, &reply, 0)) {
|
||||
uwsgi_error("uwsgi_proto_zeromq_close()/zmq_sendmsg()");
|
||||
#else
|
||||
if (zmq_send(wsgi_req->socket->pub, &reply, 0)) {
|
||||
uwsgi_error("uwsgi_proto_zeromq_close()/zmq_send()");
|
||||
#endif
|
||||
uwsgi_error("zmq_send()");
|
||||
}
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&wsgi_req->socket->lock);
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&wsgi_req->socket->lock);
|
||||
zmq_msg_close(&reply);
|
||||
|
||||
}
|
||||
|
||||
|
||||
ssize_t uwsgi_proto_zeromq_write(struct wsgi_request * wsgi_req, char *buf, size_t len) {
|
||||
int uwsgi_proto_zeromq_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
zmq_msg_t reply;
|
||||
char *zmq_body;
|
||||
|
||||
if (len == 0)
|
||||
return 0;
|
||||
if (zmq_msg_init_size(&reply, wsgi_req->proto_parser_pos + len)) {
|
||||
uwsgi_error("uwsgi_proto_zeromq_write()/zmq_msg_init_size()");
|
||||
return -1;
|
||||
}
|
||||
|
||||
zmq_body = uwsgi_concat2n(wsgi_req->proto_parser_buf, (int) wsgi_req->proto_parser_pos, buf, (int) len);
|
||||
|
||||
//uwsgi_log("|%.*s|\n", (int)wsgi_req->proto_parser_pos+len, zmq_body);
|
||||
char *zmq_body = zmq_msg_data(&reply);
|
||||
memcpy(zmq_body, wsgi_req->proto_parser_buf, wsgi_req->proto_parser_pos);
|
||||
memcpy(zmq_body + wsgi_req->proto_parser_pos, buf, len);
|
||||
|
||||
zmq_msg_init_data(&reply, zmq_body, wsgi_req->proto_parser_pos + len, uwsgi_proto_zeromq_free, NULL);
|
||||
if (uwsgi.threads > 1) pthread_mutex_lock(&wsgi_req->socket->lock);
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_lock(&wsgi_req->socket->lock);
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
if (zmq_sendmsg(wsgi_req->socket->pub, &reply, 0)) {
|
||||
#else
|
||||
if (zmq_send(wsgi_req->socket->pub, &reply, 0)) {
|
||||
#endif
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("zmq_send()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&wsgi_req->socket->lock);
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&wsgi_req->socket->lock);
|
||||
zmq_msg_close(&reply);
|
||||
return 0;
|
||||
return -1;
|
||||
}
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&wsgi_req->socket->lock);
|
||||
if (uwsgi.threads > 1)
|
||||
pthread_mutex_unlock(&wsgi_req->socket->lock);
|
||||
zmq_msg_close(&reply);
|
||||
|
||||
return len;
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
ssize_t uwsgi_proto_zeromq_sendfile(struct wsgi_request * wsgi_req) {
|
||||
/*
|
||||
|
||||
ssize_t len;
|
||||
char buf[65536];
|
||||
size_t remains = wsgi_req->sendfile_fd_size - wsgi_req->sendfile_fd_pos;
|
||||
we have a problem... recent Mongrel2 releases introduced a ring buffer that limit the amount of messages we can send (or better, the amount of
|
||||
messages mongrel2 is able to manage). If we send a big static file we can fill that buffer immediately. How to deal with this ? We know that the
|
||||
message ring can contains a fixed amount of messages. We could try to split the file in chunks (upto the maximum number supported by a specific mongrel2 instance).
|
||||
This is suboptimal, but there are no better solutions for now. Before you ask: do you really think that sending a single message with a 2GB file is a good approach ?????
|
||||
By the way, for now, waiting for a better approach, we use a 2MB buffer. Should support flawlessly files up to 32MB without being rejected by mongrel2. For bigger files you
|
||||
can tune it to higher values (or increase the mongrel2 ring buffer)
|
||||
|
||||
wsgi_req->sendfile_fd_chunk = 65536;
|
||||
*/
|
||||
|
||||
if (uwsgi.async > 1) {
|
||||
len = read(wsgi_req->sendfile_fd, buf, UMIN(remains, wsgi_req->sendfile_fd_chunk));
|
||||
if (len != (int) UMIN(remains, wsgi_req->sendfile_fd_chunk)) {
|
||||
uwsgi_error("read()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->sendfile_fd_pos += len;
|
||||
return uwsgi_proto_zeromq_write(wsgi_req, buf, len);
|
||||
#define UWSGI_MONGREL2_MAX_MSGSIZE 2*1024*1024
|
||||
int uwsgi_proto_zeromq_sendfile(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
|
||||
size_t chunk_size = UMIN( len - wsgi_req->write_pos, UWSGI_MONGREL2_MAX_MSGSIZE);
|
||||
char *tmp_buf = uwsgi_malloc(chunk_size);
|
||||
ssize_t rlen = read(fd, tmp_buf, chunk_size);
|
||||
if (rlen <= 0) {
|
||||
free(tmp_buf);
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->write_pos += rlen;
|
||||
if (uwsgi_proto_zeromq_write(wsgi_req, tmp_buf, rlen) < 0) {
|
||||
free(tmp_buf);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (remains) {
|
||||
len = read(wsgi_req->sendfile_fd, buf, UMIN(remains, wsgi_req->sendfile_fd_chunk));
|
||||
if (len != (int) UMIN(remains, wsgi_req->sendfile_fd_chunk)) {
|
||||
uwsgi_error("read()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->sendfile_fd_pos += len;
|
||||
len = uwsgi_proto_zeromq_write(wsgi_req, buf, len);
|
||||
remains = wsgi_req->sendfile_fd_size - wsgi_req->sendfile_fd_pos;
|
||||
free(tmp_buf);
|
||||
|
||||
if (wsgi_req->write_pos == len) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
|
||||
return wsgi_req->sendfile_fd_pos;
|
||||
void uwsgi_proto_zeromq_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
|
||||
char *responder = strchr(uwsgi_sock->name, ',');
|
||||
if (!responder) {
|
||||
uwsgi_log("invalid zeromq address\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_sock->receiver = uwsgi_concat2n(uwsgi_sock->name, responder - uwsgi_sock->name, "", 0);
|
||||
responder++;
|
||||
|
||||
uwsgi_sock->pub = zmq_socket(uwsgi.zmq_context, ZMQ_PUB);
|
||||
if (uwsgi_sock->pub == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
// generate uuid
|
||||
uuid_t uuid_zmq;
|
||||
uuid_generate(uuid_zmq);
|
||||
uuid_unparse(uuid_zmq, uwsgi_sock->uuid);
|
||||
|
||||
if (zmq_setsockopt(uwsgi_sock->pub, ZMQ_IDENTITY, uwsgi_sock->uuid, 36) < 0) {
|
||||
uwsgi_error("zmq_setsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (zmq_connect(uwsgi_sock->pub, responder) < 0) {
|
||||
uwsgi_error("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("zeromq UUID for responder %s on worker %d: %.*s\n", responder, uwsgi.mywid, 36, uwsgi_sock->uuid);
|
||||
|
||||
uwsgi_sock->proto = uwsgi_proto_zeromq_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_zeromq_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
uwsgi_sock->proto_add_header = uwsgi_proto_base_add_header;
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_zeromq_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_zeromq_write;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_zeromq_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_zeromq_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_zeromq_close;
|
||||
|
||||
uwsgi_sock->proto_thread_fixup = uwsgi_proto_zeromq_thread_fixup;
|
||||
|
||||
uwsgi_sock->edge_trigger = 1;
|
||||
uwsgi_sock->retry = uwsgi_malloc(sizeof(int) * uwsgi.threads);
|
||||
uwsgi_sock->retry[0] = 1;
|
||||
|
||||
// inform loop engine about edge trigger status
|
||||
uwsgi.is_et = 1;
|
||||
|
||||
|
||||
// initialize a lock for multithread usage
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_init(&uwsgi_sock->lock, NULL);
|
||||
}
|
||||
|
||||
// one pull per-thread
|
||||
if (pthread_key_create(&uwsgi_sock->key, NULL)) {
|
||||
uwsgi_error("pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
|
||||
if (tmp_zmq_pull == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
if (zmq_connect(tmp_zmq_pull, uwsgi_sock->receiver) < 0) {
|
||||
uwsgi_error("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_setspecific(uwsgi_sock->key, tmp_zmq_pull);
|
||||
|
||||
#ifdef ZMQ_FD
|
||||
size_t zmq_socket_len = sizeof(int);
|
||||
if (zmq_getsockopt(pthread_getspecific(uwsgi_sock->key), ZMQ_FD, &uwsgi_sock->fd, &zmq_socket_len) < 0) {
|
||||
uwsgi_error("zmq_getsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi_sock->fd_threads = uwsgi_malloc(sizeof(int) * uwsgi.threads);
|
||||
uwsgi_sock->fd_threads[0] = uwsgi_sock->fd;
|
||||
}
|
||||
#else
|
||||
uwsgi_sock->fd = -1;
|
||||
#endif
|
||||
|
||||
uwsgi_sock->bound = 1;
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
uwsgi_sock->recv_flag = ZMQ_DONTWAIT;
|
||||
#else
|
||||
uwsgi_sock->recv_flag = ZMQ_NOBLOCK;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -91,8 +91,6 @@ setup(name='uWSGI',
|
||||
description='The uWSGI server',
|
||||
author='Unbit',
|
||||
author_email='info@unbit.it',
|
||||
download_url='http://projects.unbit.it/downloads/uwsgi-%s.tar.gz'
|
||||
% (uc.uwsgi_version),
|
||||
license='GPL2',
|
||||
py_modules=['uwsgidecorators'],
|
||||
distclass=uWSGIDistribution,
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<%@ language="C#"%>
|
||||
|
||||
Hello 1<br/>
|
||||
<%= System.Text.Encoding.UTF8.GetString(uwsgi.api.CacheGet("/etc/passwd")) %><br/>
|
||||
Hello 1<br/>
|
||||
@@ -0,0 +1,21 @@
|
||||
Ring Test Suite
|
||||
================
|
||||
|
||||
how to build and run
|
||||
---------------------
|
||||
|
||||
* cd UWSGIROOT
|
||||
* cd t/ring
|
||||
* lein uberjar
|
||||
* cd ../..
|
||||
* uwsgi t/ring/config.ini
|
||||
* open http://localhost:9090 in your browser
|
||||
|
||||
run cases in jetty
|
||||
-------------------
|
||||
|
||||
* lein ring server
|
||||
* open http://localhost:3000 in your browser
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
[uwsgi]
|
||||
http-socket = :9090
|
||||
http-socket-modifier1 = 8
|
||||
http-socket-modifier2 = 1
|
||||
|
||||
jvm-classpath = plugins/jvm/uwsgi.jar
|
||||
jvm-classpath = t/ring/target/uwsgi-ring-tests-0.0.1-standalone.jar
|
||||
|
||||
jvm-class = uwsgi/ring/tests/app
|
||||
|
||||
ring-app = uwsgi.ring.tests.app/app
|
||||
@@ -0,0 +1,10 @@
|
||||
(defproject unbit/uwsgi-ring-tests "0.0.1"
|
||||
:description "uwsgi-ring-tests: test cases for uwsgi ring server"
|
||||
:dependencies [[org.clojure/clojure "1.4.0"]
|
||||
[compojure "1.1.5"]
|
||||
[ring/ring "1.1.0"]]
|
||||
|
||||
:source-paths ["src"]
|
||||
|
||||
:aot [uwsgi.ring.tests.app]
|
||||
)
|
||||
@@ -0,0 +1,29 @@
|
||||
(ns uwsgi.ring.tests.app
|
||||
(:use compojure.core)
|
||||
(:use [ring.middleware params
|
||||
keyword-params
|
||||
nested-params
|
||||
multipart-params])
|
||||
(:require [compojure.route :as route]
|
||||
[uwsgi.ring.tests.basic :as basic]
|
||||
[uwsgi.ring.tests.body :as body]
|
||||
[uwsgi.ring.tests.simple :as simple]
|
||||
[uwsgi.ring.tests.upload :as upload])
|
||||
(:gen-class
|
||||
:main true))
|
||||
|
||||
(defn app-routes [req]
|
||||
(if (= (get req :uri) "/")
|
||||
(basic/index-page req)
|
||||
((routes simple/app-routes body/app-routes upload/app-routes (route/not-found "<h1>Page not found</h1>")) req)))
|
||||
|
||||
(def app
|
||||
(-> app-routes
|
||||
wrap-keyword-params
|
||||
wrap-nested-params
|
||||
wrap-params
|
||||
wrap-multipart-params))
|
||||
|
||||
(defn -main [& args]
|
||||
(println "uwsgi ring tests app loaded"))
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
(ns uwsgi.ring.tests.basic)
|
||||
|
||||
(defn index-page [req] {:status 200
|
||||
:headers { "Content-Type" "text/html" , "Server" "uWSGI" }
|
||||
:body (str "<h1>Ring test suites</h1>"
|
||||
"<h2>Simple tests</h2>"
|
||||
"<ul>"
|
||||
"<li><a href='/hello'>hello</a></li>"
|
||||
"<li><a href='/echo?msg=abc'>echo</a></li>"
|
||||
"<li><a href='/palindrome?msg=abc'>palindrome</a></li>"
|
||||
"</ul>"
|
||||
"<h2>Body type tests</h2>"
|
||||
"<ul>"
|
||||
"<li><a href='/sequence'>sequence</a></li>"
|
||||
"<li><a href='/file'>file</a></li>"
|
||||
"<li><a href='/stream'>stream</a></li>"
|
||||
"</ul>"
|
||||
"<h2>Upload tests</h2>"
|
||||
"<form action='/upload' enctype='multipart/form-data' method='post'>"
|
||||
"<p>"
|
||||
"Please select a file<br>"
|
||||
"<input type='file' name='file' size='40'>"
|
||||
"</p>"
|
||||
"<input type='submit' value='Upload'>"
|
||||
"</form>"
|
||||
"<h2>Other tests</h2>"
|
||||
"<ul>"
|
||||
"<li>...</li>"
|
||||
"</ul>")})
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
(ns uwsgi.ring.tests.body
|
||||
(:use [compojure.core]))
|
||||
|
||||
; generating primary numbers
|
||||
; http://clojuredocs.org/clojure_core/clojure.core/lazy-seq#example_1000
|
||||
(defn sieve [s]
|
||||
(cons (first s)
|
||||
(lazy-seq (sieve (filter #(not= 0 (mod % (first s)))
|
||||
(rest s))))))
|
||||
|
||||
(defn numsequence [] (take 20 (sieve (iterate inc 2))))
|
||||
|
||||
(defn file [] (java.io.File. "CONTRIBUTORS"))
|
||||
|
||||
(defn stream [] (java.io.FileInputStream. (java.io.File. "CONTRIBUTORS")))
|
||||
|
||||
(defroutes app-routes
|
||||
(GET "/sequence" [] (numsequence))
|
||||
(GET "/file" [] (file))
|
||||
(GET "/stream" [] (stream)))
|
||||
@@ -0,0 +1,14 @@
|
||||
(ns uwsgi.ring.tests.simple
|
||||
(:use [compojure.core]) )
|
||||
|
||||
(defn hello [] "Hello, World!")
|
||||
|
||||
(defn echo [msg] msg)
|
||||
|
||||
(defn palindrome [msg] (clojure.string/reverse msg) )
|
||||
|
||||
(defroutes app-routes
|
||||
(GET "/hello" [] (hello) )
|
||||
(GET "/echo" [msg] (echo msg) )
|
||||
(GET "/palindrome" [msg] (palindrome msg) )
|
||||
)
|
||||
@@ -0,0 +1,20 @@
|
||||
(ns uwsgi.ring.tests.upload
|
||||
(:use [compojure.core]))
|
||||
|
||||
(defn upload-file [fname fsize fbody] {
|
||||
:status 200
|
||||
:headers { "Content-Type" "text/html" , "Server" "uWSGI" }
|
||||
:body (str "<h1>Uploaded file</h1>"
|
||||
"<ul>"
|
||||
"<li>" fname "</li>"
|
||||
"<li>" fsize "</li>"
|
||||
"</ul>")})
|
||||
|
||||
(defroutes app-routes
|
||||
(POST "/upload" {params :params}
|
||||
(let [file (params :file)
|
||||
file-name (file :filename)
|
||||
file-size (file :size)
|
||||
file-body (file :tempfile)]
|
||||
(upload-file file-name file-size file-body))))
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- Edited by XMLSpy® -->
|
||||
<catalog>
|
||||
<cd>
|
||||
<title>Quintessence</title>
|
||||
<artist>Borknagar</artist>
|
||||
</cd>
|
||||
<cd>
|
||||
<title>Torn Beyond Reason</title>
|
||||
<artist>Woods Of Desolation</artist>
|
||||
</cd>
|
||||
<cd>
|
||||
<title>Autumn Aurora</title>
|
||||
<artist>Drudkh</artist>
|
||||
</cd>
|
||||
<cd>
|
||||
<title>Om</title>
|
||||
<artist>Negura Bunget</artist>
|
||||
</cd>
|
||||
<cd>
|
||||
<title>Frostnacht</title>
|
||||
<artist>Helrunar</artist>
|
||||
</cd>
|
||||
</catalog>
|
||||
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0"?>
|
||||
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
||||
|
||||
<xsl:template match="/">
|
||||
<html>
|
||||
<body>
|
||||
<h2>Blackmetal albums</h2>
|
||||
<table border="1">
|
||||
<tr bgcolor="black">
|
||||
<th style="color:white">Title</th>
|
||||
<th style="color:white">Artist</th>
|
||||
</tr>
|
||||
<xsl:for-each select="catalog/cd">
|
||||
<tr>
|
||||
<td><xsl:value-of select="title"/></td>
|
||||
<td><xsl:value-of select="artist"/></td>
|
||||
<td>-<xsl:value-of select="$foobar"/>-</td>
|
||||
<td><xsl:value-of select="$agent"/></td>
|
||||
</tr>
|
||||
</xsl:for-each>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
</xsl:template>
|
||||
</xsl:stylesheet>
|
||||
@@ -0,0 +1,5 @@
|
||||
[uwsgi]
|
||||
http-socket = :9090
|
||||
plugin = xslt
|
||||
xml_storage = t/xslt
|
||||
route = /(.*)$ xslt:doc=%(xml_storage)/$1.xml,stylesheet=%(xml_storage)/$1.xml.xslt,content_type=text/html,params=foobar=test&agent=${HTTP_USER_AGENT}
|
||||
@@ -1,51 +0,0 @@
|
||||
/* taken from http://wiki.unbit.it/UnbitKernel */
|
||||
struct uidsec_struct {
|
||||
/* network limits */
|
||||
unsigned short ipv4_tcp_port;
|
||||
unsigned short ipv4_udp_port;
|
||||
unsigned short ipv4_tcp_control_port;
|
||||
|
||||
int ipv4_tcp_socket_protection;
|
||||
unsigned long long ipv4_firewall_mask;
|
||||
|
||||
/* limits */
|
||||
int fs_readonly;
|
||||
|
||||
/* process markers */
|
||||
int domain_id;
|
||||
int fcgi_id;
|
||||
int scgi_id;
|
||||
int apps_id;
|
||||
int wapp_id;
|
||||
int ssh_id;
|
||||
int cron_id;
|
||||
|
||||
/* thread ? */
|
||||
int cloned_vm;
|
||||
|
||||
/* process limit */
|
||||
int max_dom_proc;
|
||||
int max_apps_proc;
|
||||
int max_apps_thread;
|
||||
int max_ssh_proc;
|
||||
int max_cron_proc;
|
||||
|
||||
/* misc */
|
||||
int control_uid;
|
||||
int listen_backlog;
|
||||
int errors;
|
||||
|
||||
/* counters */
|
||||
int accept_cnt;
|
||||
int accept_last;
|
||||
|
||||
int fork_cnt;
|
||||
int fork_last;
|
||||
|
||||
unsigned long long bio_read;
|
||||
unsigned long long bio_write;
|
||||
|
||||
int memory_errors;
|
||||
|
||||
};
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
int uwsgi_init(int, char **, char **);
|
||||
|
||||
int main(int argc, char *argv[], char **environ) {
|
||||
return uwsgi_init(argc, argv, environ);
|
||||
}
|
||||
+68
-34
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.9-dev'
|
||||
uwsgi_version = '1.9.1'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -64,7 +64,6 @@ report['pcre'] = False
|
||||
report['matheval'] = False
|
||||
report['routing'] = False
|
||||
report['capabilities'] = False
|
||||
report['ini'] = False
|
||||
report['yaml'] = False
|
||||
report['json'] = False
|
||||
report['ldap'] = False
|
||||
@@ -228,7 +227,7 @@ def build_uwsgi(uc, print_only=False):
|
||||
continue
|
||||
p = p.strip()
|
||||
if p == 'ugreen':
|
||||
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
|
||||
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku' or uwsgi_os.startswith('CYGWIN'):
|
||||
continue
|
||||
epc += "UDEP(%s);" % p
|
||||
eplc += "ULEP(%s);" % p
|
||||
@@ -291,7 +290,7 @@ def build_uwsgi(uc, print_only=False):
|
||||
p = p.strip()
|
||||
|
||||
if p == 'ugreen':
|
||||
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku':
|
||||
if uwsgi_os == 'OpenBSD' or uwsgi_cpu[0:3] == 'arm' or uwsgi_os == 'Haiku' or uwsgi_os.startswith('CYGWIN'):
|
||||
continue
|
||||
path = 'plugins/%s' % p
|
||||
path = path.rstrip('/')
|
||||
@@ -311,6 +310,12 @@ def build_uwsgi(uc, print_only=False):
|
||||
p_cflags = cflags[:]
|
||||
p_cflags += up['CFLAGS']
|
||||
|
||||
if uwsgi_os.startswith('CYGWIN'):
|
||||
try:
|
||||
p_cflags.remove('-fstack-protector')
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
p_cflags.remove('-Wdeclaration-after-statement')
|
||||
except:
|
||||
@@ -416,6 +421,20 @@ def build_uwsgi(uc, print_only=False):
|
||||
for pb in post_build:
|
||||
pb(uc)
|
||||
|
||||
def open_profile(filename):
|
||||
if filename.startswith('http://') or filename.startswith('https://') or filename.startswith('ftp://'):
|
||||
wrapped = False
|
||||
try:
|
||||
import urllib2
|
||||
except:
|
||||
import urllib.request
|
||||
wrapped = True
|
||||
|
||||
if wrapped:
|
||||
import io
|
||||
return io.TextIOWrapper(urllib.request.urlopen(filename), encoding='utf-8')
|
||||
return urllib2.urlopen(filename)
|
||||
return open(filename)
|
||||
|
||||
class uConf(object):
|
||||
|
||||
@@ -423,8 +442,6 @@ class uConf(object):
|
||||
self.config = ConfigParser.ConfigParser()
|
||||
if not mute:
|
||||
print("using profile: %s" % filename)
|
||||
if not os.path.exists(filename):
|
||||
raise Exception("profile not found !!!")
|
||||
|
||||
if os.path.exists('uwsgibuild.lastprofile'):
|
||||
ulp = open('uwsgibuild.lastprofile','r')
|
||||
@@ -437,13 +454,13 @@ class uConf(object):
|
||||
ulp.write(filename)
|
||||
ulp.close()
|
||||
|
||||
self.config.read(filename)
|
||||
self.config.readfp(open_profile(filename))
|
||||
self.gcc_list = ['core/utils', 'core/protocol', 'core/socket', 'core/logging', 'core/master', 'core/master_utils', 'core/emperor',
|
||||
'core/notify', 'core/mule', 'core/subscription', 'core/stats', 'core/sendfile', 'core/async', 'core/master_checks',
|
||||
'core/offload', 'core/io', 'core/static', 'core/websockets', 'core/spooler', 'core/snmp', 'core/exceptions',
|
||||
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm',
|
||||
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events',
|
||||
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb',
|
||||
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini',
|
||||
'core/rpc', 'core/gateway', 'core/loop', 'core/rb_timers', 'core/uwsgi']
|
||||
# add protocols
|
||||
self.gcc_list.append('proto/base')
|
||||
@@ -526,7 +543,8 @@ class uConf(object):
|
||||
for option in self.config.options('uwsgi'):
|
||||
interpolations[option] = self.get(option)
|
||||
iconfig = ConfigParser.ConfigParser(interpolations)
|
||||
iconfig.read(inherit)
|
||||
iconfig.readfp(open_profile(inherit))
|
||||
|
||||
for opt in iconfig.options('uwsgi'):
|
||||
if not self.config.has_option('uwsgi', opt):
|
||||
self.set(opt, iconfig.get('uwsgi', opt))
|
||||
@@ -609,7 +627,6 @@ class uConf(object):
|
||||
self.libs.append('-lkvm')
|
||||
|
||||
if uwsgi_os == 'Haiku':
|
||||
self.set('async', 'false')
|
||||
self.libs.remove('-rdynamic')
|
||||
self.libs.remove('-lpthread')
|
||||
self.libs.append('-lroot')
|
||||
@@ -640,6 +657,8 @@ class uConf(object):
|
||||
pass
|
||||
elif uwsgi_os == 'Darwin':
|
||||
locking_mode = 'osx_spinlock'
|
||||
elif uwsgi_os.startswith('CYGWIN'):
|
||||
locking_mode = 'windows_mutex'
|
||||
|
||||
if locking_mode == 'pthread_mutex':
|
||||
self.cflags.append('-DUWSGI_LOCK_USE_MUTEX')
|
||||
@@ -648,6 +667,8 @@ class uConf(object):
|
||||
self.cflags.append('-DUWSGI_LOCK_USE_POSIX_SEM')
|
||||
elif locking_mode == 'osx_spinlock':
|
||||
self.cflags.append('-DUWSGI_LOCK_USE_OSX_SPINLOCK')
|
||||
elif locking_mode == 'windows_mutex':
|
||||
self.cflags.append('-DUWSGI_LOCK_USE_WINDOWS_MUTEX')
|
||||
|
||||
if locking_mode == 'auto':
|
||||
report['locking'] = 'sysv semaphores'
|
||||
@@ -666,8 +687,10 @@ class uConf(object):
|
||||
if int(sun_major) >= 5:
|
||||
if int(sun_minor) >= 10:
|
||||
event_mode = 'port'
|
||||
elif uwsgi_os in ('Darwin', 'FreeBSD', 'OpenBSD', 'NetBSD'):
|
||||
elif uwsgi_os in ('Darwin', 'FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly'):
|
||||
event_mode = 'kqueue'
|
||||
elif uwsgi_os.startswith('CYGWIN'):
|
||||
event_mode = 'poll'
|
||||
|
||||
if event_mode == 'epoll':
|
||||
self.cflags.append('-DUWSGI_EVENT_USE_EPOLL')
|
||||
@@ -677,6 +700,8 @@ class uConf(object):
|
||||
self.cflags.append('-DUWSGI_EVENT_USE_DEVPOLL')
|
||||
elif event_mode == 'port':
|
||||
self.cflags.append('-DUWSGI_EVENT_USE_PORT')
|
||||
elif event_mode == 'poll':
|
||||
self.cflags.append('-DUWSGI_EVENT_USE_POLL')
|
||||
|
||||
report['event'] = event_mode
|
||||
|
||||
@@ -758,8 +783,10 @@ class uConf(object):
|
||||
|
||||
if self.get('as_shared_library'):
|
||||
self.ldflags.append('-shared')
|
||||
self.ldflags.append('-fPIC')
|
||||
self.cflags.append('-fPIC')
|
||||
# on cygwin we do not need PIC (it is implicit)
|
||||
if not uwsgi_os.startswith('CYGWIN'):
|
||||
self.ldflags.append('-fPIC')
|
||||
self.cflags.append('-fPIC')
|
||||
self.cflags.append('-DUWSGI_AS_SHARED_LIBRARY')
|
||||
if uwsgi_os == 'Darwin':
|
||||
self.ldflags.append('-dynamiclib')
|
||||
@@ -829,7 +856,7 @@ class uConf(object):
|
||||
if self.has_include('uuid/uuid.h'):
|
||||
has_uuid = True
|
||||
self.cflags.append("-DUWSGI_UUID")
|
||||
if uwsgi_os == 'Linux' or os.path.exists('/usr/lib/libuuid.so') or os.path.exists('/usr/local/lib/libuuid.so') or os.path.exists('/usr/lib64/libuuid.so') or os.path.exists('/usr/local/lib64/libuuid.so'):
|
||||
if uwsgi_os == 'Linux' or uwsgi_os.startswith('CYGWIN') or os.path.exists('/usr/lib/libuuid.so') or os.path.exists('/usr/local/lib/libuuid.so') or os.path.exists('/usr/lib64/libuuid.so') or os.path.exists('/usr/local/lib64/libuuid.so'):
|
||||
self.libs.append('-luuid')
|
||||
|
||||
if self.get('append_version'):
|
||||
@@ -907,11 +934,6 @@ class uConf(object):
|
||||
self.cflags.append('-DUWSGI_VERSION_REVISION="' + uver_rev + '"')
|
||||
self.cflags.append('-DUWSGI_VERSION_CUSTOM="\\"' + uver_custom + '\\""')
|
||||
|
||||
if self.get('ini'):
|
||||
self.cflags.append("-DUWSGI_INI")
|
||||
self.gcc_list.append('core/ini')
|
||||
report['ini'] = True
|
||||
|
||||
if self.get('yaml'):
|
||||
self.cflags.append("-DUWSGI_YAML")
|
||||
self.gcc_list.append('core/yaml')
|
||||
@@ -1065,38 +1087,41 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
|
||||
print("Error: unable to find directory '%s'" % path)
|
||||
sys.exit(1)
|
||||
|
||||
sys.path.insert(0, path)
|
||||
import uwsgiplugin as up
|
||||
if sys.argv[1] != '--plugin':
|
||||
reload(up)
|
||||
up = {}
|
||||
try:
|
||||
execfile('%s/uwsgiplugin.py' % path, up)
|
||||
except:
|
||||
f = open('%s/uwsgiplugin.py' % path)
|
||||
exec(f.read(), up)
|
||||
f.close()
|
||||
|
||||
requires = []
|
||||
|
||||
p_cflags = cflags[:]
|
||||
p_ldflags = ldflags[:]
|
||||
|
||||
p_cflags += up.CFLAGS
|
||||
p_ldflags += up.LDFLAGS
|
||||
p_libs = up.LIBS
|
||||
p_cflags += up['CFLAGS']
|
||||
p_ldflags += up['LDFLAGS']
|
||||
p_libs = up['LIBS']
|
||||
|
||||
post_build = None
|
||||
|
||||
try:
|
||||
requires = up.REQUIRES
|
||||
requires = up['REQUIRES']
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
post_build = up.post_build
|
||||
post_build = up['post_build']
|
||||
except:
|
||||
pass
|
||||
|
||||
p_cflags.insert(0, '-I.')
|
||||
|
||||
if name is None:
|
||||
name = up.NAME
|
||||
name = up['NAME']
|
||||
else:
|
||||
p_cflags.append("-D%s_plugin=%s_plugin" % (up.NAME, name))
|
||||
p_cflags.append("-D%s_plugin=%s_plugin" % (up['NAME'], name))
|
||||
|
||||
try:
|
||||
for opt in uc.config.options(name):
|
||||
@@ -1116,7 +1141,7 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
|
||||
if uwsgi_os == 'Darwin':
|
||||
shared_flag = '-dynamiclib -undefined dynamic_lookup'
|
||||
|
||||
for cfile in up.GCC_LIST:
|
||||
for cfile in up['GCC_LIST']:
|
||||
if cfile.endswith('.a'):
|
||||
gcc_list.append(cfile)
|
||||
elif not cfile.endswith('.c') and not cfile.endswith('.cc') and not cfile.endswith('.m'):
|
||||
@@ -1159,10 +1184,19 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
|
||||
except:
|
||||
pass
|
||||
|
||||
#for ofile in up.OBJ_LIST:
|
||||
# gcc_list.insert(0,ofile)
|
||||
if uwsgi_os.startswith('CYGWIN'):
|
||||
try:
|
||||
p_cflags.remove('-fstack-protector')
|
||||
p_ldflags.remove('-fstack-protector')
|
||||
except:
|
||||
pass
|
||||
|
||||
gccline = "%s -fPIC %s -o %s.so %s %s %s %s" % (GCC, shared_flag, plugin_dest, ' '.join(uniq_warnings(p_cflags)), ' '.join(gcc_list), ' '.join(uniq_warnings(p_ldflags)), ' '.join(uniq_warnings(p_libs)) )
|
||||
need_pic = ' -fPIC'
|
||||
# on cygwin we do not need PIC
|
||||
if uwsgi_os.startswith('CYGWIN'):
|
||||
need_pic = ' -L. -luwsgi'
|
||||
|
||||
gccline = "%s%s %s -o %s.so %s %s %s %s" % (GCC, need_pic, shared_flag, plugin_dest, ' '.join(uniq_warnings(p_cflags)), ' '.join(gcc_list), ' '.join(uniq_warnings(p_ldflags)), ' '.join(uniq_warnings(p_libs)) )
|
||||
print("[%s] %s.so" % (GCC, plugin_dest))
|
||||
|
||||
ret = os.system(gccline)
|
||||
|
||||
Reference in New Issue
Block a user