Compare commits

...
438 Commits
Author SHA1 Message Date
roberto@precise64 4707d9250d queue/cache fix 2012-03-14 11:34:51 +01:00
roberto@precise64 d719960411 fixed emperor amqp 2012-03-14 10:03:54 +01:00
roberto@precise64 734818c995 fixed shared sockets 2012-03-14 08:28:25 +01:00
roberto@precise64 a35335a820 fixed lua plugin 2012-03-12 18:54:04 +01:00
roberto@precise64 aca4dbfbe7 fixed threading rpc 2012-03-12 14:54:59 +01:00
roberto@precise64 b036029b32 another locking fix 2012-03-12 09:58:02 +01:00
roberto@freebsd64 52f3e757ed added --ftok 2012-03-12 09:40:56 +01:00
roberto@precise64 c4ce1cf7d8 appliead Riccardo's patches 2012-03-11 20:10:04 +01:00
roberto@icarus 48175d0759 various fixed for php and cgi plugins, added notfound plugin 2012-03-11 17:21:53 +00:00
roberto@precise64 2932168db7 Added tag 1.1-rc1 for changeset 1d1702789710 2012-03-10 15:23:47 +01:00
roberto@precise64 e8d96b8f84 completed ldap support 2012-03-10 15:21:08 +01:00
roberto@precise64 bd15fd9da1 fixed ldap support 2012-03-10 14:30:48 +01:00
roberto@precise64 6e98eda963 set version to 1.1, only LDAP missing 2012-03-10 13:34:17 +01:00
roberto@precise64 ec9bb3601e added --flock/--flock2/--flock-wait/--flock-wait2 2012-03-10 13:26:45 +01:00
roberto@precise64 02e4840b29 re-added --ignore-sigpipe 2012-03-10 12:34:45 +01:00
roberto@precise64 d7e8523fcf do not call atexit hooks in async mode 2012-03-10 12:06:19 +01:00
roberto@precise64 41464c3bfa fr sctp fix 2012-03-10 11:35:05 +01:00
roberto@goyle a3617d0b5a fastrouter heavy optimization 2012-03-10 11:25:19 +01:00
roberto@centos6 10ff849ebd fixed permissions of files 2012-03-07 15:06:38 +01:00
roberto@centos6 c2f7d487d0 initgroups() usage 2012-03-07 04:40:16 +01:00
roberto@centos6 395cf57e21 added stats for sctp fastrouter 2012-03-07 02:55:48 +01:00
roberto@centos6 4c854a83c9 SCTP improvements, rack optimizations 2012-03-07 01:40:57 +01:00
roberto@centos6 881b3b7e0c another series of SCTP fixes 2012-03-06 16:43:41 +01:00
roberto@openbsd50 bb28e4279b fixed cgi cast of FILE 2012-03-06 15:22:38 +01:00
roberto@openbsd50 c65b8ce162 various fixes 2012-03-06 15:20:25 +01:00
roberto@openindiana 8a303b1965 solaris fixes 2012-03-06 12:19:29 +01:00
roberto@centos6 adca811941 fixed 105 2012-03-06 11:34:56 +01:00
roberto@goyle f79e9d8773 fixed a typo 2012-03-05 16:22:20 +01:00
roberto@precise64 629fbf4f07 another series of sctp patch 2012-03-05 04:29:11 +01:00
roberto@precise64 da9ce52294 little refactoring for the fastrouter 2012-03-04 16:10:35 +01:00
roberto@precise64 205605a3c4 fixed PATH_INFO in php 2012-03-03 17:34:44 +01:00
roberto@precise64 e39127be92 ready for rc 2012-03-03 16:31:26 +01:00
roberto@precise64 0b2458d74a SCTP is experimenta, stop development til 1.1 release 2012-03-03 16:17:16 +01:00
roberto@precise64 9d661122bd added experimental SCTP/persistent connections support 2012-03-03 13:46:21 +01:00
roberto@precise64 8518747a51 try to reduce spooler wait 2012-03-03 09:35:46 +01:00
roberto@precise64 2f6450a560 <app> tag usage will be removed in uWSGI 1.2 2012-03-02 08:27:52 +01:00
roberto@precise64 c72889c10f added --daemonize2 2012-03-02 07:31:20 +01:00
roberto@precise64 bb7456e3f8 gateways structure is again shared 2012-03-01 21:27:17 +01:00
roberto@precise64 5aff13543e another fastrouter fix 2012-03-01 20:11:06 +01:00
roberto@precise64 c7d967d43c fixed python 3 2012-03-01 18:30:32 +01:00
roberto@precise64 1a42194304 added ruby rvm/gemset support 2012-03-01 18:22:25 +01:00
roberto@precise64 312563437c multiprocess spooler 2012-03-01 14:54:10 +01:00
roberto@precise64 5972ac1ed7 fixed permission in ipcsem 2012-03-01 11:11:51 +01:00
roberto@precise64 75d4123b34 added locking test 2012-03-01 11:06:53 +01:00
roberto@precise64 89ef4f68a9 added ipcsem 2012-03-01 11:06:00 +01:00
roberto@precise64 ed72677e52 even fcntl is broken 2012-03-01 09:51:31 +01:00
roberto@precise64 08ab27c36c cache_get optimization 2012-03-01 09:15:43 +01:00
roberto@precise64 af8bb8fd05 fixed locking in multithread 2012-03-01 09:06:02 +01:00
roberto@precise64 57bade7eae close stdin in vassals 2012-02-29 14:57:44 +01:00
roberto@mishmash 3c6de0e84d various fastrouter fixes 2012-02-29 10:14:44 +01:00
roberto@precise64 24e3fea334 added fd:// to corerouter bind subsystem 2012-02-29 08:47:52 +01:00
roberto@precise64 6af77aab8b added --fastrouter-gracetime 2012-02-29 07:46:24 +01:00
roberto@precise64 12325633ed fastrouter improvements 2012-02-29 07:04:14 +01:00
roberto@sirius 3a108b61ee fixed pause reporting 2012-02-28 18:56:32 +01:00
roberto@goyle b2eaf384ac --fastrouter-fallback 2012-02-28 18:08:40 +01:00
roberto@precise64 3d17ef9603 lockf for sun 2012-02-28 10:31:24 +01:00
roberto@precise64 3b031872f7 lockf for sun 2012-02-28 10:30:07 +01:00
roberto@precise64 e97d39f37c prepared umtx for future implementations 2012-02-28 09:21:44 +01:00
roberto@sirius 763f715279 ported locking api to OSX 2012-02-28 09:18:41 +01:00
roberto@precise64 af9f79f3eb ported new locking api to linux 2012-02-28 09:14:08 +01:00
roberto@freebsd64 01ab3e2895 broken commit for new locking api 2012-02-28 09:05:37 +01:00
roberto@precise64 7a34344632 fixed a bug in setrlimit 2012-02-27 20:21:55 +01:00
roberto@precise64 9714cb6790 fixed log flush 2012-02-27 19:48:35 +01:00
roberto@precise64 aa981d03e8 reintroduce the remote spooler plugin [2] 2012-02-27 15:59:47 +01:00
roberto@precise64 9a09164fc3 reintroduce the remote spooler plugin 2012-02-27 15:59:07 +01:00
roberto@precise64 9674a81323 added --forkbomb-delay 2012-02-27 14:38:49 +01:00
roberto@precise64 aba7280691 added --need-app 2012-02-27 14:27:34 +01:00
roberto@precise64 ef9908b058 fixed --cluster-reload and --cluster-log 2012-02-26 12:35:05 +01:00
roberto@precise64 4da4fb4cbd completed clustering porting 2012-02-26 12:30:35 +01:00
roberto@precise64 b4f8a3b179 fixed bug #62 2012-02-26 09:07:14 +01:00
roberto@precise64 b48a955848 fixed paste logging 2012-02-26 08:57:43 +01:00
roberto@precise64 5ea4e3bcc3 removed url from setup.py 2012-02-26 08:26:21 +01:00
roberto@precise64 6732cb01a8 free libxml2 resources on exit 2012-02-26 08:05:39 +01:00
roberto@precise64 0b5ca736d4 re-added expat support 2012-02-25 20:26:17 +01:00
roberto@precise64 a2358c6bec completed porting of the http plugin to the new api 2012-02-25 18:36:04 +01:00
roberto@precise64 10775dd2ac another series of http ports 2012-02-25 18:24:56 +01:00
roberto@precise64 d33d12c642 ported --http-var 2012-02-25 18:20:59 +01:00
roberto@precise64 af3ccfeed4 added negative configlogic 2012-02-25 09:24:07 +01:00
roberto@precise64 1d64267aba added --check-static-docroot 2012-02-25 08:44:00 +01:00
roberto@cable 9bbef9b0c5 various condition build fixes 2012-02-25 08:34:11 +01:00
roberto@precise64 c95ec82b03 a series of php/cgi fixes 2012-02-24 12:12:19 +01:00
roberto@precise64 46108a00f0 fixed startup time in rack plugin 2012-02-24 09:37:33 +01:00
roberto@precise64 d6c3fd7771 --php-app added 2012-02-24 09:26:57 +01:00
roberto@precise64 ad783ccaf0 added script for external app loading 2012-02-24 06:49:54 +01:00
roberto@precise64 f58be4241f added cheaper_backlog2 example 2012-02-23 21:46:27 +01:00
roberto@precise64 cb1d22d88b added pluggable cheaper algorithms 2012-02-23 21:38:53 +01:00
roberto@precise64 6c8453d98e another logging refactoring 2012-02-23 20:42:00 +01:00
roberto@colossus 061de3b037 merge 2012-02-23 18:16:38 +01:00
roberto@colossus ded065ef38 php-server-software 2012-02-23 18:16:18 +01:00
roberto@precise64 822959238c fixed a bug with --set 2012-02-23 16:58:36 +01:00
roberto@precise64 4ebb9d7b46 faster restart thanks to single getrlimit call 2012-02-23 14:13:38 +01:00
roberto@precise64 cc49964c43 fixed a lost null pointer 2012-02-23 07:51:36 +01:00
roberto@precise64 3787d5e84a flush logs on exit 2012-02-23 07:48:54 +01:00
roberto@precise64 7329606a6a added a cast (just to be sure) 2012-02-22 17:11:12 +01:00
roberto@precise64 5facafadea added uwsgi api support for php 2012-02-22 16:44:56 +01:00
roberto@precise64 d3102df2bf added a signal handler for FPE 2012-02-22 12:00:32 +01:00
roberto@precise64 87860da238 better loaded app reporting 2012-02-22 11:55:06 +01:00
roberto@precise64 4a8aa01f40 added startup time for apps 2012-02-22 11:39:19 +01:00
roberto@longshot 9d35067b4b allows custom php-config path 2012-02-22 10:33:45 +01:00
roberto@precise64 1c29be3745 fix php uwsgi.h include 2012-02-20 04:07:16 +01:00
roberto@centos6 bf3c3a3768 another php update 2012-02-19 17:52:17 +01:00
roberto@fedora32 b25de79ae4 completed new php plugin 2012-02-19 15:44:23 +01:00
roberto@precise64 ba663ef2cc ready for new php plugin 2012-02-19 11:08:52 +01:00
roberto@precise64 19185640a5 fixed a typo 2012-02-18 16:29:21 +01:00
roberto@precise64 eafe8c4fff new cheaper implementation 2012-02-18 16:28:01 +01:00
roberto@precise64 bdd3e69024 removed some funny debug log 2012-02-18 11:40:25 +01:00
roberto@precise64 b5a7ab3688 fixed paste logging 2012-02-18 09:32:39 +01:00
roberto@centos64 cc0fa8dee6 fixed rack build 2012-02-18 08:55:35 +01:00
roberto@precise64 14941cc1c0 deprecate <app> 2012-02-18 08:40:36 +01:00
roberto@precise64 910cb3a790 fixed single-intepreter mode 2012-02-18 08:32:53 +01:00
roberto@precise64 355e989eea refactored xmlconf 2012-02-18 08:07:48 +01:00
roberto@precise64 bfcd9dad25 removed useless makefiles 2012-02-18 07:37:48 +01:00
roberto@precise64 73ed5fd7cf added --auto-weight 2012-02-18 07:25:11 +01:00
roberto@netbsd64 d21cc0970c NetBSD fixes 2012-02-18 08:16:37 +01:00
roberto@precise64 eb8b03139d master_loop function is becoming extremely huge, time to refactor it... 2012-02-17 20:36:04 +01:00
roberto@precise64 1558145985 refactored uwsgi_reload() 2012-02-17 20:23:29 +01:00
roberto@precise64 4ea9a29e62 fixed some typo in comments 2012-02-17 20:09:54 +01:00
roberto@precise64 72c8d9cd5e refactored/reimplemented cheaper mode 2012-02-17 19:04:32 +01:00
roberto@precise64 fb4fc38f14 better umask handling 2012-02-17 17:58:46 +01:00
roberto@precise64 de25db9e75 fixed shared sockets for http and fastrouter plugins 2012-02-17 17:48:57 +01:00
roberto@precise64 4ba558430d added wrr to fastrouter/subscription 2012-02-17 13:57:46 +01:00
roberto@precise64 e4711484ac fixed a stupid deadlock 2012-02-17 11:21:08 +01:00
roberto@precise64 5081a3f635 placed a mutex in threaded logger trying to fix #84 2012-02-17 09:50:56 +01:00
roberto@precise64 b31fa366a2 make older gcc happy for gevent 2012-02-17 07:05:26 +01:00
roberto@precise64 c1b24b390a fixed unsubscribe 2012-02-16 20:13:36 +01:00
roberto@precise64 b7461442b0 added a report on unsubscribe 2012-02-16 16:56:08 +01:00
roberto@precise64 c072e9b609 added stacktrace to perl errors 2012-02-16 11:31:52 +01:00
roberto@precise64 5236c58255 added new routing rules 2012-02-16 09:04:59 +01:00
roberto@precise64 4f5280ea2b zeromq/mongrel2 improvements 2012-02-16 07:33:31 +01:00
roberto@precise64 4d1c3fcaea added UWSGI_APPID management in router_uwsgi 2012-02-16 07:22:13 +01:00
roberto@precise64 310acaf4cc do not inizialize request plugins if not needed 2012-02-15 21:28:12 +01:00
roberto@precise64 8111acaad1 completed new perl infrastructure 2012-02-15 20:34:52 +01:00
roberto@mrspurr c80b10d2b2 fixes for non ithreads perl 2012-02-15 19:55:43 +01:00
roberto@precise64 9807192bd1 thread-safe perl multi-app support 2012-02-15 18:10:22 +01:00
roberto@precise64 9386c97851 added perl multiple interpreter support (non-thread-safe) 2012-02-15 14:10:33 +01:00
roberto@precise64 7f3e9b10c4 merge 2012-02-15 05:03:56 +01:00
roberto@precise64 360719582b fix #91 2012-02-15 05:03:15 +01:00
roberto@sirius a1a6d4a248 fxed the carbon plugin 2012-02-14 16:20:34 +01:00
roberto@precise64 015ea78927 set correct status in routers 2012-02-13 19:27:42 +01:00
roberto@precise64 ad32841aaa fixed wrong definition of --route option 2012-02-13 19:22:32 +01:00
roberto@precise64 2a3771dccf added blacklist/whitelist support for options 2012-02-13 16:55:48 +01:00
roberto@precise64 26af8af48f fixed port handling in fastrouter stats 2012-02-13 11:54:03 +01:00
roberto@precise64 5829c3a843 new plugin infrastructure 2012-02-13 11:40:06 +01:00
roberto@goyle c723d6d9d5 non-linux fix 2012-02-13 07:56:59 +01:00
roberto@oneiric64 2c0c9a918a fixed a stupid bug in uniq_warning 2012-02-13 06:41:27 +01:00
roberto@precise64 8f9bc7170e added zergpool pluin 2012-02-12 17:20:51 +01:00
roberto@precise64 ee002167d4 improved zergpool 2012-02-12 17:17:19 +01:00
roberto@precise64 4ddeb26cca extended zerg mode to support an unlimited number of sockets 2012-02-12 13:16:58 +01:00
roberto@precise64 a1514e2eaf added another config style for basicauth 2012-02-12 10:11:39 +01:00
roberto@precise64 5d1c7ab8b0 fixed a race condition in cheaper + threads 2012-02-12 09:42:17 +01:00
roberto@precise64 27698e34f5 added protected.ini 2012-02-12 09:28:19 +01:00
roberto@precise64 c06b4773c7 thread-safe basicauth 2012-02-12 09:26:38 +01:00
roberto@mrspurr e431936a8e python set() is not good 2012-02-12 08:43:21 +01:00
roberto@precise64 de3d22a401 preliminary support for http basic auth (real) 2012-02-12 08:35:21 +01:00
roberto@precise64 22778d9de7 preliminary support for http basic auth 2012-02-12 08:34:14 +01:00
roberto@precise64 069f517b04 added --zerg-fallback 2012-02-11 21:02:15 +01:00
roberto@precise64 1017dda1ec merge 2012-02-11 17:50:20 +01:00
roberto@centos64 581b4a4216 off by one fix 2012-02-11 17:40:41 +01:00
roberto@precise64 e1f00cbf96 better erlang detection 2012-02-11 17:20:47 +01:00
roberto@centos64 32ad0a7b87 build improvements 2012-02-11 14:17:00 +01:00
roberto@oneiric64 aa4b9b16fb fixed magic_table handling 2012-02-10 16:14:44 +01:00
roberto@oneiric64 73721ab73a disable write-strings 2012-02-10 15:27:02 +01:00
roberto@oneiric64 90cc3dc389 fixed rack build 2012-02-10 12:37:07 +01:00
roberto@oneiric64 f4f4d5a6c0 python atexit improvements from mod_wsgi 2012-02-10 11:18:53 +01:00
roberto@oneiric64 4bd2410ee7 added support for logic in config directives with a first 'for' implementation 2012-02-10 09:06:09 +01:00
roberto@gambit 6bc264d33b various fixes for better cgi routing support 2012-02-09 13:00:27 +01:00
roberto@gambit c7d1c6818b fixed touch-reload 2012-02-09 12:32:31 +01:00
roberto@oneiric64 937e68bf67 another lock fix 2012-02-08 12:56:46 +01:00
roberto@oneiric64 434fb96be7 another fix in locking subsystem 2012-02-08 12:49:06 +01:00
roberto@oneiric64 e2fe86027c improved pyargv management 2012-02-08 12:19:14 +01:00
roberto@oneiric64 06ca891d94 fixed threading in command mode 2012-02-08 11:54:15 +01:00
roberto@oneiric64 57c00c9b12 set to_hell in command mode 2012-02-08 11:41:01 +01:00
roberto@sirius b320e1e222 disable master process in command mode 2012-02-08 11:15:29 +01:00
roberto@sirius c72ddc9dd8 added command mode 2012-02-08 11:01:04 +01:00
roberto@oneiric64 c37a386674 added uwsgi.is_locked 2012-02-07 16:40:25 +01:00
roberto@oneiric64 ad6a79b5b7 remove -Wwrite-strings 2012-02-07 16:09:45 +01:00
roberto@oneiric64 ff733cd50b fixed logto 2012-02-07 15:37:19 +01:00
roberto@oneiric64 53128a2391 fixed daemonize and cron 2012-02-07 15:32:34 +01:00
roberto@oneiric64 d01fc8804c fixed a stupid bug in cron management 2012-02-07 14:36:26 +01:00
roberto@oneiric64 e520d7a58f fixed mules signal handling 2012-02-07 12:38:37 +01:00
roberto@freebsd64 7846ea636c ported new locking api to freebsd 2012-02-07 12:09:20 +01:00
roberto@mrspurr 0025ad8329 ported new lock api to OSX 2012-02-07 12:03:50 +01:00
roberto@oneiric64 1a1f270f4e completed locking refactoring on linux 2012-02-07 11:56:19 +01:00
roberto@oneiric64 517f4498f5 another locking refactoring 2012-02-07 11:10:20 +01:00
roberto@oneiric64 87a165477f fixed disable logging 2012-02-07 05:34:28 +01:00
roberto@oneiric64 1e657f0b77 plugins loading fix 2012-02-07 05:26:51 +01:00
roberto@oneiric64 a8e399db1e psgi fixes 2012-02-07 05:08:53 +01:00
roberto@oneiric64 66f9607404 various fixes reported by Lukasz Mierzwa 2012-02-07 03:20:10 +01:00
roberto@oneiric64 27319c2da3 ported --http-manage-expect to new options api 2012-02-06 17:23:22 +01:00
roberto@oneiric64 de21abb21c ported jvm plugin to the new options api 2012-02-06 17:17:26 +01:00
roberto@oneiric64 94cae4ac17 completed php porting to the new api 2012-02-06 17:01:16 +01:00
roberto@oneiric64 3b5e1f98f5 completed fastrouter porting to the new options api 2012-02-06 16:56:06 +01:00
roberto@oneiric64 594f67c6d7 added support for paste loggers 2012-02-06 16:29:04 +01:00
roberto@oneiric64 f1b415df2f completed python plugin porting to the new options api 2012-02-06 16:14:15 +01:00
roberto@oneiric64 c07e0ef581 --touch-logreopen and --touch-logrotate 2012-02-06 16:00:51 +01:00
roberto@goyle 0d4f6501b0 ported backtrace to osx 2012-02-06 11:38:56 +01:00
roberto@goyle d2cbb7eea2 allow non-pcre build 2012-02-06 11:02:57 +01:00
roberto@oneiric64 f4cb3c67c1 a series of stupid fixes 2012-02-05 11:56:50 +01:00
roberto@oneiric64 a51877cd1d another series of options fixes/porting 2012-02-05 11:50:33 +01:00
roberto@oneiric64 c0c3287f74 fully ported cgi plugin to the new options api 2012-02-05 11:44:18 +01:00
roberto@oneiric64 83378802af completed porting perl/psgi to new options api 2012-02-05 11:25:39 +01:00
roberto f05d712923 completed ruby/rack porting to the new options api 2012-02-05 11:20:19 +01:00
roberto@freebsd64 5b2df55b8e ported freebsd to the new locking api 2012-02-05 11:07:40 +01:00
roberto@oneiric64 865ec4dd8f added internal routing subsystem 2012-02-05 10:43:03 +01:00
roberto@oneiric64 6ddf1afc81 ported --http-use-cache to the new api 2012-02-04 16:20:37 +01:00
roberto@mrspurr 7bd44f4f14 added internal routing infrastructure 2012-02-04 16:10:32 +01:00
roberto@goyle a92c2003ee prepare for new routing system 2012-02-02 18:20:10 +01:00
roberto@debian64 97a8c5e4b6 another fix for pyargv 2012-02-02 11:40:52 +01:00
roberto@debian64 a5aa31f13e applied ticket #82 2012-02-02 11:25:44 +01:00
roberto@debian64 1a0161cb6b fixed pyargv 2012-02-02 11:14:34 +01:00
roberto@debian64 b8c17baf7c fixed pythonpath 2012-02-02 11:08:02 +01:00
roberto@debian64 e161ea3f0a another fix for locking 2012-02-02 11:04:51 +01:00
roberto@debian64 fb827a274b started porting rack plugin to the new options api 2012-02-02 10:29:31 +01:00
roberto@debian64 7281318ef6 fixed bug #79 2012-02-02 10:20:57 +01:00
roberto@debian64 80be7385ed fixed locking 2012-02-02 09:59:48 +01:00
roberto@debian64 8913dda413 added uwsgi_tmpname() 2012-02-02 09:07:39 +01:00
roberto@debian64 b8ad90104b another series of fastrouter patches 2012-02-02 09:01:53 +01:00
roberto@debian64 2646109986 ported --fastrouter option 2012-02-02 08:56:47 +01:00
roberto@oneiric64 cf247c828a fixed emperor reload in lazy mode 2012-02-01 17:53:50 +01:00
roberto@debian64 28106e624e fixed http protocol bug 2012-02-01 16:41:50 +01:00
roberto@debian64 30e8420342 added --cheaper-overload 2012-02-01 16:07:29 +01:00
roberto@debian64 99e4d55e9b ported pthread mutex to the new api 2012-02-01 15:32:33 +01:00
roberto@goyle f9daec9e43 implementation of lock detector 2012-02-01 14:30:26 +01:00
roberto@goyle 68a2902ce3 fixed readlink in binary path 2012-01-31 11:46:30 +01:00
roberto@goyle 4b2db3de57 started revamp of the JVM plugin 2012-01-31 11:15:05 +01:00
roberto@goyle c4c526df17 fixed gateways in non-master mode 2012-01-31 11:03:19 +01:00
roberto@goyle 15ad5531b0 another series of updates 2012-01-31 10:54:29 +01:00
roberto@goyle c0af1c1094 ported rrdtool plugin 2012-01-31 10:44:28 +01:00
roberto@goyle 9b89333244 ported lua 2012-01-31 10:40:38 +01:00
roberto@goyle 1863030078 ported ping and nagios 2012-01-31 10:38:44 +01:00
roberto@goyle 15055ffa0d ported psgi to the new api 2012-01-31 10:31:46 +01:00
roberto@oneiric64 8391ce28f7 ported max vars to new options api 2012-01-30 11:09:59 +01:00
roberto@oneiric64 b38791a357 ported chmod-socket to new options api 2012-01-30 10:46:20 +01:00
roberto@oneiric64 53ba043168 ported logdate to new options api 2012-01-30 10:37:44 +01:00
roberto@oneiric64 d46a8dba7b ported snmp to new options api 2012-01-30 10:26:28 +01:00
roberto@oneiric64 1e62afc161 ported zerg to new options api 2012-01-30 09:33:59 +01:00
roberto@oneiric64 03cf6e868f ported mule subsystem to the new options api 2012-01-30 08:26:30 +01:00
roberto@oneiri64 e1da28ccc3 ported static file serving to the new options api 2012-01-30 08:21:04 +01:00
roberto@oneiric64 4173ca36cb ported map-socket to the new api 2012-01-30 08:05:52 +01:00
roberto@oneiric64 c393de492d ported ksm 2012-01-29 08:53:08 +01:00
roberto@oneiric64 f9a716d70f fixed dynamic options 2012-01-29 08:51:45 +01:00
roberto@oneiric64 2e8655c203 ported pidfile signal to the new api 2012-01-29 08:49:07 +01:00
roberto@oneiric64 42b7164f33 ported sqlite3 to the new api 2012-01-29 08:21:33 +01:00
roberto@oneiric64 602d49b045 ported cap/unshare to the new api 2012-01-29 08:04:05 +01:00
roberto@oneiric64 58a67df534 ported uid/gid to new api 2012-01-29 07:59:56 +01:00
roberto@oneiric64 de6cc04685 added exec:// facility 2012-01-29 07:52:39 +01:00
roberto@oneiric64 33763e074d ported spooler to the new options api 2012-01-28 17:40:24 +01:00
roberto@oneiric64 32b0f8efb6 ported queue and cache to new options api 2012-01-28 17:32:34 +01:00
roberto@oneiric64 644618963a another series of options porting 2012-01-28 17:14:49 +01:00
roberto@oneiric64 97ac31376e added --never-swap 2012-01-28 17:04:37 +01:00
roberto@oneiric64 e5ec0f0221 even simpler options hook 2012-01-28 16:37:20 +01:00
roberto@oneiric64 5875ddc355 refactored first part of clustering 2012-01-28 15:42:50 +01:00
roberto@oneiric64 f7d5f4692d another series of options ported to the new api 2012-01-28 15:14:41 +01:00
roberto@oneiric64 d85bc64aa9 ported uwsgi_help to the new api 2012-01-28 09:29:57 +01:00
roberto@oneiric64 a18ed0503c implemented flag subsystem for options 2012-01-28 08:57:17 +01:00
roberto@oneiric64 77a4e3771b ported plugin loading to the new api 2012-01-28 07:40:20 +01:00
roberto@oneiric64 7523eb1cb0 ported short options to new api 2012-01-27 19:37:37 +01:00
roberto@oneiric64 46f8ee9410 ported xml config to new option/help api 2012-01-27 18:24:55 +01:00
roberto@oneiric64 f0aa9f9fd2 another part of options refactoring 2012-01-27 17:54:31 +01:00
roberto@oneiric64 73d5cadd8c massive refactoring of options management (broken, do not use this rev) 2012-01-27 16:30:00 +01:00
roberto@oneiric64 1a0e2076d5 restore termios on exit (if required) 2012-01-25 07:19:25 +01:00
roberto@oneiric64 6db3dab5ea added --pyshell-oneshot 2012-01-25 06:32:02 +01:00
roberto@oneiric64 20856549c1 fixed a double free in spooler 2012-01-24 21:33:24 +01:00
roberto@oneiric64 d570845592 fixed sigquit/sigint in hijacked mode 2012-01-24 21:13:24 +01:00
roberto@oneiric64 eed27c0aac implemented rack.input.gets and expect-continue in http router 2012-01-24 21:11:17 +01:00
roberto@oneiric64 daef139496 added --http-manage-expect 2012-01-24 18:57:29 +01:00
roberto@oneiric64 3690d836b0 another refactoring of corerouter 2012-01-23 17:36:59 +01:00
roberto@oneiric64 93faeb4177 first round of common code base for routers 2012-01-23 16:04:10 +01:00
roberto@oneiric64 095b9154e0 fixed signal handling in gateways 2012-01-23 12:33:57 +01:00
roberto@oneiric64 f86aa55220 destructive commit for http and fastrouter plugins 2012-01-23 12:13:05 +01:00
roberto@oneiric64 40f7aecbba fixed a race condition in SIGINT/SIGQUIT 2012-01-22 17:55:09 +01:00
roberto@oneiric64 5d9d67caa4 preliminary refactoring for multithreaded fastrouter/removed fastfuncs support 2012-01-22 11:48:13 +01:00
roberto@oneiric64 0f00d6fb23 added --fastrouter-post-buffering-dir 2012-01-21 17:36:15 +01:00
roberto@oneiric64 61b0e68641 added UWSGI_POSTFILE 2012-01-21 04:26:02 +01:00
roberto@oneiric64 6ed38ced3c preliminary infrastructure for fastrouter buffering 2012-01-21 03:02:09 +01:00
roberto@app2 7a681a97b5 added --exec-in-jail 2012-01-20 16:55:54 +00:00
roberto@app2 41008fa594 fix a bunch of spooler issue 2012-01-20 15:16:47 +00:00
roberto@oneiric64 fb13084b87 applied patch #76 by prymitive 2012-01-20 10:59:39 +01:00
roberto@oneiric64 3f9023281e added --exec-pre-jail and --exec-post-jail 2012-01-20 09:18:18 +01:00
roberto@oneiric64 4e21fe6607 fix uwsgi.atexit when threading mode is enabled 2012-01-18 05:01:22 +01:00
roberto@oneiric64 7a95c726cd segmentation fault manager (linux only) 2012-01-15 04:33:19 +01:00
roberto@oneiric64 940401e0f8 second round of multispooler patches 2012-01-14 06:56:11 +01:00
roberto@oneiric64 86bfb20903 applied first part of multispooler patch 2012-01-14 06:00:33 +01:00
roberto@oneiric64 e21cf87285 fixed atexit 2012-01-13 04:26:20 +01:00
roberto@oneiric64 65f1445b64 bumped to 1.1 and added uwsgi.atexit 2012-01-12 19:25:54 +01:00
roberto@oneiric64 f87761d092 fix for invalid --http address 2012-01-11 11:14:31 +01:00
roberto@oneiric64 0c712ac28d added --no-harakiri-arh 2012-01-11 05:05:15 +01:00
roberto@oneiric64 db301531d0 added uwsgi.after_req_hook 2012-01-10 20:30:46 +01:00
roberto@oneiric64 4c82a72fd5 FreeBSD9 fix 2012-01-10 19:08:00 +01:00
roberto@oneiric64 7417e582c3 a fix for subscription system 2012-01-10 18:06:46 +01:00
roberto@oneiric64 e32564c7b2 added --fastrouter-harakiri 2012-01-10 15:58:49 +01:00
roberto@oneiric64 798bc482dc fixed a leak in cgi plugin 2012-01-10 14:00:36 +01:00
roberto@oneiric64 c7e7f756bc do not build netlink support by default 2012-01-10 13:43:13 +01:00
roberto@oneiric64 24358701f7 added Roy to contributors 2012-01-06 22:03:29 +01:00
roberto@netbsd64 f1e392c0a0 added support for post_buffering in cgi plugin 2012-01-06 22:57:58 +01:00
roberto@netbsd64 5e8d38d8bc support body_as_file in cgi plugin 2012-01-06 22:21:08 +01:00
roberto@oneiric64 4650d2edbb added support for indexed cgi vars 2012-01-06 19:36:42 +01:00
roberto@oneiric64 b153033514 fixed PATH_INFO and SCRIPT_NAME in cgi plugin 2012-01-06 18:23:07 +01:00
roberto@netbsd64 6dcbce5eb7 added binary detection for NetBSD 2012-01-05 22:47:50 +01:00
roberto@oneiric64 4ceeab439a fixed a typo 2012-01-05 21:14:45 +01:00
roberto@oneiric64 8b1a6be9da various realpath fixes 2012-01-05 21:10:02 +01:00
roberto@netbsd64 baeb864075 fixed #70 2012-01-05 21:28:47 +01:00
roberto@netbsd64 c88e1c3619 realpath on BSD is different from Linux/Solaris/OSX 2012-01-05 21:25:21 +01:00
roberto@oneiric64 1b04df7c5e Added tag 1.0.1 for changeset 8fe7bb792399 2012-01-03 17:12:16 +01:00
roberto@oneiric64 237f11dba3 fixed http protocol post optimization 2012-01-03 13:44:53 +01:00
roberto@oneiric64 313f1c2f29 make some gcc OSX version happy 2012-01-02 16:53:06 +01:00
roberto@oneiric64 f0862f3bc7 Added tag 1.0 for changeset 3c7092733585 2011-12-30 08:25:31 +01:00
roberto@oneiric64 1a8850ffe5 fixed cache monitor 2011-12-28 19:36:34 +01:00
roberto@genesi e640f812ba added cache monitor from Riccardo Magliocchetti in contrib/ 2011-12-28 04:32:21 +01:00
roberto@genesi 75ea170472 report hostname in welcome.py 2011-12-27 12:18:32 +01:00
roberto@debian32 1b14b1926e dded changelog for 1.0 2011-12-27 08:18:32 +01:00
roberto@oneiric64 edaed7ab01 fixed x-accel-redirect (temp workaround) 2011-12-26 08:26:14 +01:00
roberto@oneiric64 6cceece3d7 (really) fixed fibers plugin 2011-12-26 08:18:01 +01:00
roberto@oneiric64 2add03edb8 closed bug #67 2011-12-25 23:09:54 +01:00
roberto@oneiric64 7aab9bae51 report tiem delta in idle mode 2011-12-24 11:15:18 +01:00
roberto@oneiric64 46c2c1d885 moved version string to 1.0 2011-12-23 17:47:54 +01:00
roberto@oneiric64 544e97fac0 do not export original-proc-name in uwsgi.opt 2011-12-23 12:52:27 +01:00
roberto@oneiric64 265a700498 added --cheaper-step 2011-12-22 13:23:34 +01:00
roberto@oneiric64 a657b4b0aa Added tag 1.0-rc10 for changeset af490b8c30f8 2011-12-22 07:37:45 +01:00
roberto@oneiric64 ac97c8cf34 php plugin is now in beta 2011-12-21 15:46:23 +01:00
roberto@oneiric64 545f3ee608 gratily improved the php plugin 2011-12-21 15:00:14 +01:00
roberto@oneiric64 fcd1a36420 added --static-index 2011-12-21 11:02:36 +01:00
roberto@fiorenzo 47a8ab3da9 fixed fastrouter when nodes are on non-existent unix-socket 2011-12-21 11:00:45 +01:00
roberto@oneiric64 c4375a8e7a better ordering of options 2011-12-21 09:36:06 +01:00
roberto@oneiric64 a6c5bd3bb3 fixed optional-argument support 2011-12-21 07:56:19 +01:00
roberto@oneiric64 d53127e8cf fixed Makefile after php inclusion 2011-12-20 11:57:51 +01:00
roberto@oneiric64 851dd987ab added alpha-quality php plugin 2011-12-20 11:33:03 +01:00
roberto@goyle cf582af970 added --fastrouter-zerg 2011-12-19 09:37:46 +01:00
roberto@oneiric64 d0ec331b6b do not daemonize in emperor mode 2011-12-19 07:52:42 +01:00
roberto@oneiric64 cc75f5f7b3 fixed a stupid bug in emperor 2011-12-17 22:01:45 +01:00
roberto@oneiric64 3d08b7fdd0 added --cflags as build option 2011-12-17 14:02:52 +01:00
roberto@oneiric64 7a92449fc3 another binname improvement 2011-12-16 12:17:53 +01:00
roberto@oneiric64 4b3c34469d fixed bin-name implicit plugin loading 2011-12-16 11:51:07 +01:00
roberto@oneiric64 55bf34561e detect misusage of --rails 2011-12-16 06:49:04 +01:00
roberto@oneiric64 7e79dc0405 removed a debug line in uwsgidecorators 2011-12-15 09:21:17 +01:00
roberto@oneiric64 d3053523ab completed logging pluginization 2011-12-14 10:50:25 +01:00
roberto@oneiric64 e32185cc14 added --threaded-logger 2011-12-14 09:10:26 +01:00
roberto@oneiric64 8e3e3cf27b set level to 5 in graylog2 plugin 2011-12-13 20:42:39 +01:00
roberto@oneiric64 e2cea376e8 added rsyslog plugin 2011-12-13 20:33:17 +01:00
roberto@oneiric64 2a27b66d96 ported zeromq logging to the new api 2011-12-13 19:02:58 +01:00
roberto@oneiric64 522717ca99 initial structure for logging plugins (post-1.0) 2011-12-13 18:21:23 +01:00
roberto@oneiric64 5ee106170b added contrib/cgi_python.c 2011-12-13 06:40:10 +01:00
roberto@oneiric64 d62f04a5a6 cgi loadlib 2011-12-13 06:25:18 +01:00
roberto@oneiric64 eefe5048b2 fixed threading in multiple apps 2011-12-12 17:41:49 +01:00
roberto@oneiric64 8f792fde2d export daemons infos in stats server 2011-12-12 15:15:15 +01:00
roberto@oneiric64 d8ef2d8300 added CLONE_NEWPID for future unshare() improvements 2011-12-12 13:11:50 +01:00
roberto@oneiric64 e69dd5cb6a remove unshare call() on older kernels 2011-12-12 12:54:25 +01:00
roberto@oneiric64 8acd57d87e Added tag 1.0-rc9 for changeset 5da6fe43a8c2 2011-12-12 12:03:39 +01:00
roberto@oneiric64 a42aa1a273 raise exception on rack.input gets/each 2011-12-12 11:49:28 +01:00
roberto@sirius 4b2b7ccf82 fixed rack.input in older rails releases 2011-12-12 11:46:10 +01:00
roberto@Oneiric64 e0fa180a23 --cgi-allowed-ext --cgi-unset 2011-12-11 12:01:40 +01:00
roberto@oneiric64 06ea1fcd1b better SCRIPT_NAME handling in cgi plugin 2011-12-11 11:47:23 +01:00
roberto@oneiric64 567bcc582d improved PATH_INFO in cgi plugin 2011-12-11 11:09:20 +01:00
roberto@oneiric64 844f8c71fa more apache-compliant cgi plugin 2011-12-11 10:40:23 +01:00
roberto@oneiric64 bddbbb93cd first round of improvements for the cgi plugin 2011-12-10 13:37:11 +01:00
roberto@oneiric64 310cc83d36 --exec-as-user 2011-12-09 17:56:57 +01:00
roberto@oneiric64 23dcdc5863 added linux unshare() support 2011-12-09 17:26:33 +01:00
roberto@oneiric64 1286e1835c more tolerant cache checks 2011-12-09 07:42:49 +01:00
roberto@oneiric64 613f2ed939 fixed --rails wirh ruby 1.9.2 2011-12-08 18:36:40 +01:00
roberto@oneiric64 46108f8d0c include st.h in ruby1.8 2011-12-08 08:34:40 +01:00
roberto@oneiric64 28dcfa4131 added SpoolProc class in uwsgidsl.rb 2011-12-08 08:30:25 +01:00
roberto@oneiric64 b48597d3c3 completed spooler support in ruby 2011-12-08 08:09:38 +01:00
roberto@oneiric64 fe4c6ba13e you can now write spooler tasks in ruby 2011-12-08 06:40:29 +01:00
roberto@oneiric64 4049493ffd Added tag 1.0-rc8 for changeset 365e2514cc19 2011-12-07 10:23:54 +01:00
roberto@oneiric64 0c9b6e98f7 added support for yaml lists under libyaml 2011-12-07 10:21:11 +01:00
roberto@colossus ce33d0be5a support for older rails apps 2011-12-07 09:21:28 +01:00
roberto@oneiric64 4f0fb90bff added failcnt in subscription system 2011-12-06 11:17:26 +01:00
roberto@mrspurr 66eff0107a fixed SEQPACKET usage 2011-12-06 10:50:30 +01:00
roberto@oneoric64 82f83e610f fixed a fd leak on static file serving 2011-12-06 09:29:41 +01:00
roberto@oneiric64 cf7df391ad correctly report load in fastrouter stats 2011-12-04 15:58:38 +01:00
roberto@oneiric64 244c9f8204 allows modifier2 to be subscribed 2011-12-04 15:35:29 +01:00
roberto@oneoric64 26dc19df7d reverted subscription string usage 2011-12-04 15:30:08 +01:00
roberto@oneiric64 7b8bff1a08 fixed a bug in load value 2011-12-04 13:50:18 +01:00
roberto@oneiric64 0b010124ef subscription optimizations 2011-12-04 13:45:18 +01:00
roberto@oneiric64 c7bde15f39 ready for next (last?) -rc 2011-12-04 10:38:53 +01:00
roberto@oneiric64 b941e4f2f0 pep8 setup.py 2011-12-04 07:41:49 +01:00
roberto@oneiric64 536c6e7e29 pep8 uwsgidecorators 2011-12-04 07:39:01 +01:00
roberto@oneiric64 dfe4abec35 added health_check in log_pipe 2011-12-04 07:14:19 +01:00
roberto@oneiric64 693b80d7d3 fixed healthcheck skip 2011-12-03 11:06:30 +01:00
roberto@oneiric64 c9e6475ef4 fixed another leak in master 2011-12-03 08:26:41 +01:00
roberto@oneiric64 b745132ebd improved ksm support 2011-12-02 13:31:17 +01:00
roberto@oneiric64 19686cb19f update the copyright to 2011 in apache module 2011-12-01 14:18:54 +01:00
roberto@oneiric64 e0c0593b5b fixed a memory leak in glob() 2011-12-01 13:45:52 +01:00
roberto@oneiric64 415a8af363 fix compilation with async=false 2011-12-01 05:44:23 +01:00
roberto@oneiric64 d44777b1b4 fixed mod_uwsgi when SCRIPT_NAME = / 2011-11-30 18:47:14 +01:00
roberto@oneiric64 e3ff3037b4 use vector-io in fileserve mode 2011-11-30 18:38:42 +01:00
roberto@oneiric64 7add30fd31 added uWSGIemptyRemoteUser in mod_uwsgi 2011-11-30 15:37:48 +01:00
roberto@fiorenzo 501cd0349b another fastrouter fix/optimization 2011-11-29 20:52:08 +01:00
roberto@oneiric64 7b4e3f6601 better error reporting in fastrouter 2011-11-29 19:34:29 +01:00
roberto@oneiric64 8622c2780c fixed cheap reporting 2011-11-29 16:17:17 +01:00
roberto@oneiric64 13de7b6d5b fixed a loop in subscription system 2011-11-29 13:29:23 +01:00
roberto@fiorenzo 53cb864f9c added death mark in fastrouter stats 2011-11-29 11:50:09 +01:00
roberto@fiorenzo 72f693f02a fixed subscription rr and added --fastrouter-stats 2011-11-29 11:46:50 +01:00
roberto@genesi fb80e32682 fix obsolete kernel check 2011-11-29 10:41:57 +01:00
roberto@oneiric64 1db3426ee1 applied riccardo's fix for sendfile 2011-11-29 07:52:26 +01:00
roberto@oneiric64 a44879e384 improved lazy mode to allows signals 2011-11-29 07:47:19 +01:00
roberto@oneiric64 c0075c817d remove unneeded debug entry 2011-11-28 22:06:08 +01:00
roberto@oneiric64 177dc3322b remove unneded rb_gc_unregister_address 2011-11-28 21:57:35 +01:00
roberto@storm 21ef4fc89b multiline headers rack fixes 2011-11-28 21:36:03 +01:00
roberto@oneiric64 f467643f6f better post_buffering 2011-11-28 14:14:24 +01:00
roberto@oneiric64 3db41e7e05 better usage of fwrite() 2011-11-28 14:04:49 +01:00
roberto@oneiric64 73151729c6 mark route() requests 2011-11-28 13:58:15 +01:00
roberto@longshot 5d9c415028 merge 2011-11-28 13:07:05 +01:00
roberto@longshot b92ed4da4e fixed after_request remapper 2011-11-28 13:06:43 +01:00
roberto@oneiric64 2d1a9a03d2 reduce a potetial race conditions in evil reloads 2011-11-28 11:35:35 +01:00
roberto@longshot 5d6edd2321 force removal of -Winline during plugins building 2011-11-28 10:29:46 +01:00
roberto@oneiric64 365f4ba83f fixed a bug in FIFO reading 2011-11-28 07:17:58 +01:00
roberto@oneiric64 66e30ae293 report config in USR1 management 2011-11-27 21:05:06 +01:00
roberto@oneiric64 728425de19 Added tag 1.0-rc7 for changeset a3ca2e8e27c5 2011-11-26 18:50:41 +01:00
roberto@oneiric64 b0af1f800b fixed a bug in #ifdef for pump/web3 spotted by riccardo 2011-11-26 18:39:44 +01:00
roberto@oneiric64 543271e856 fixed a ksm leak 2011-11-26 13:02:47 +01:00
roberto@oneiric64 a1564a44fa added postgresql probe 2011-11-26 12:44:38 +01:00
roberto@oneiric64 571029cfd3 added probe infrastructure 2011-11-26 11:05:49 +01:00
roberto@oneiric64 579eaa630a refactored daemons and removed uwsgi.attach_daemon function 2011-11-26 09:04:19 +01:00
roberto@oneiric64 9530c8ffe0 applied riccardo's patch [2] 2011-11-26 08:10:29 +01:00
roberto@oneiric64 0d8690091b applied riccardo's patch [1] 2011-11-26 08:04:39 +01:00
roberto@goyle 5b5e3a1ec1 added delta_requests 2011-11-25 15:34:41 +01:00
roberto@centos64 869ae5e3ed allows the building of uWSGI on ancient linux kernel (like CentOS4) 2011-11-24 12:57:08 +01:00
roberto@oneiric64 d6dc8d86f8 added subscription report on startup 2011-11-24 07:42:14 +01:00
roberto@oneiric64 758745be68 closed bug #56 2011-11-24 07:35:32 +01:00
roberto@oneiric64 2adfa56d6a added threading name in python threads object 2011-11-23 17:44:41 +01:00
roberto@oneiric64 a4c728f5df added auto-patching for Rack::BodyProxy.each 2011-11-23 11:45:13 +01:00
roberto@oneiric64 5c06341b7f ready for -rc7 2011-11-23 10:08:49 +01:00
roberto@oneiric64 6f57902a9b another cron fix 2011-11-23 05:37:00 +01:00
roberto@longshot a3e118893d do not build sqlite on unbit 2011-11-22 18:52:12 +01:00
roberto@oneiric64 ff2d3c29d6 fixed a bug in cron management 2011-11-22 17:56:03 +01:00
roberto@oneiric64 59a8df85f2 added --st as a --subscribe/--subscribe-to alias 2011-11-22 11:23:10 +01:00
roberto@oneiric64 e303bd182a report subscribed nodes timeout 2011-11-22 11:15:13 +01:00
roberto@oneiric64 dcef9a497c less verbose build system 2011-11-22 09:46:16 +01:00
roberto@oneiric64 8d4fd66aaf fixed a bug in execvp() during reload on 64 bit 2011-11-22 09:16:34 +01:00
roberto@debian32 471bd23acf added --subscribe-freq and --subscription-tolerance 2011-11-21 20:22:00 +01:00
roberto@debian32 ffcef81dd0 greatly improved subscription system 2011-11-21 16:23:24 +01:00
roberto@debian32 317df5d06b added @(filename) magic var 2011-11-21 13:22:05 +01:00
roberto@debian32 ad7b5efd6f added --logfile-chmod 2011-11-21 10:32:48 +01:00
roberto@deban32 891f770724 added Lukas to CONTRIBUTORS 2011-11-21 09:55:43 +01:00
roberto@debian32.local 0b6d715982 refactored ping and nagios 2011-11-21 09:42:48 +01:00
roberto@debian32 76c2415516 moved cluster-related functions to a dedicated file 2011-11-20 11:36:42 +01:00
roberto@gambit 3260faca17 Added tag 1.0-rc6 for changeset a2b8f25fd17e 2011-11-19 08:40:45 +01:00
154 changed files with 16154 additions and 7734 deletions
+8
View File
@@ -37,3 +37,11 @@ fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
4e4e781ef89ac33e71a7e92741d54549240ed156 1.0-rc3
24f7e260ea345c2cd73e2fd8191dddbd1b039062 1.0-rc4
043ba93dd69cf6924e98db3cb9a8759cce997367 1.0-rc5
a2b8f25fd17ed7424d1470a287d0b3144d2a12c8 1.0-rc6
a3ca2e8e27c5c12c44ba0cacb4de4cb51377f184 1.0-rc7
365e2514cc19f0366365318f12a1d63113b02924 1.0-rc8
5da6fe43a8c29056bc9442c684615e11a3699795 1.0-rc9
af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
3c70927335856883283fe4db448e092cecc0ccdb 1.0
8fe7bb792399cb6e6a24e20551f4149409660363 1.0.1
1d1702789710ec1c20613d2490b14f70756e67ec 1.1-rc1
+4
View File
@@ -14,3 +14,7 @@ Cal Leeming, Simplicity Media Ltd
Luigi Scarso
Corey Farwell
Charles Duffy
Lukas Lalinsky
Steven Fernandez
Łukasz Mierzwa
Roy Marples
+25
View File
@@ -1,3 +1,28 @@
*** 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]
-2
View File
@@ -1,2 +0,0 @@
all:
python2.4 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python2.5 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python2.6 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python2.7 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python3.0 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python3.1 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python3.2 uwsgiconfig.py --build
-2
View File
@@ -1,2 +0,0 @@
all:
python uwsgiconfig.py --build pylua
+39 -4
View File
@@ -2,7 +2,7 @@
*** uWSGI/mod_uwsgi ***
Copyright 2009-2010 Unbit S.a.s. <info@unbit.it>
Copyright 2009-2011 Unbit S.a.s. <info@unbit.it>
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -73,6 +73,7 @@ typedef struct {
char scheme[9];
int cgi_mode ;
int max_vars;
int empty_remote_user;
} uwsgi_cfg;
module AP_MODULE_DECLARE_DATA uwsgi_module;
@@ -162,6 +163,7 @@ static void *uwsgi_server_config(apr_pool_t *p, server_rec *s) {
c->cgi_mode = 0 ;
c->max_vars = 128;
c->script_name[0] = 0;
c->empty_remote_user = 1;
return c;
}
@@ -177,6 +179,7 @@ static void *uwsgi_dir_config(apr_pool_t *p, char *dir) {
c->modifier2 = 0 ;
c->cgi_mode = 0 ;
c->max_vars = 128;
c->empty_remote_user = 1;
c->script_name[0] = 0;
if (dir) {
if (strcmp(dir, "/")) {
@@ -344,7 +347,15 @@ static int uwsgi_handler(request_rec *r) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SERVER_PROTOCOL", r->protocol, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REQUEST_URI", r->unparsed_uri, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_ADDR", r->connection->remote_ip, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user ? r->user : "", &pkt_size) ;
//
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", r->user, &pkt_size) ;
}
else if (c->empty_remote_user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "REMOTE_USER", "", &pkt_size) ;
}
if (r->user) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "AUTH_TYPE", (char *) ap_auth_type(r), &pkt_size) ;
}
@@ -354,7 +365,8 @@ static int uwsgi_handler(request_rec *r) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "UWSGI_SCHEME", c->scheme, &pkt_size) ;
}
if (c->script_name[0] != 0) {
// SCRIPT_NAME = "/" is like SCRIPT_NAME = ""
if (c->script_name[0] != 0 && !(c->script_name[0] == '/' && c->script_name[1] == 0)) {
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "SCRIPT_NAME", c->script_name, &pkt_size) ;
vecptr = uwsgi_add_var(uwsgi_vars, vecptr, r, "PATH_INFO", r->uri+strlen(c->script_name), &pkt_size) ;
}
@@ -621,7 +633,7 @@ static const char * cmd_uwsgi_force_cgi_mode(cmd_parms *cmd, void *cfg, const ch
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value)) {
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
c->cgi_mode = 1 ;
}
@@ -722,6 +734,28 @@ static const char * cmd_uwsgi_socket(cmd_parms *cmd, void *cfg, const char *path
return NULL ;
}
static const char * cmd_uwsgi_empty_remote_user(cmd_parms *cmd, void *cfg, const char *value) {
uwsgi_cfg *c ;
if (cfg) {
c = cfg ;
}
else {
c = ap_get_module_config(cmd->server->module_config, &uwsgi_module);
}
if (!strcmp("yes", value) || !strcmp("on", value) || !strcmp("enable", value) || !strcmp("1", value) || !strcmp("true", value)) {
c->empty_remote_user = 1;
}
else {
c->empty_remote_user = 0;
}
return NULL ;
}
static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE12("uWSGIsocket", cmd_uwsgi_socket, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path and optional timeout in seconds of uwsgi server socket"),
AP_INIT_TAKE1("uWSGIsocket2", cmd_uwsgi_socket2, NULL, RSRC_CONF|ACCESS_CONF, "Absolute path of failover uwsgi server socket"),
@@ -730,6 +764,7 @@ static const command_rec uwsgi_cmds[] = {
AP_INIT_TAKE1("uWSGIforceScriptName", cmd_uwsgi_force_script_name, NULL, ACCESS_CONF, "Fix for PATH_INFO/SCRIPT_NAME when the location has filesystem correspondence"),
AP_INIT_TAKE1("uWSGIforceCGImode", cmd_uwsgi_force_cgi_mode, NULL, ACCESS_CONF, "Force uWSGI CGI mode for perfect integration with apache filter"),
AP_INIT_TAKE1("uWSGIforceWSGIscheme", cmd_uwsgi_force_wsgi_scheme, NULL, ACCESS_CONF, "Force the WSGI scheme var (set by default to \"http\")"),
AP_INIT_TAKE1("uWSGIemptyRemoteUser", cmd_uwsgi_empty_remote_user, NULL, ACCESS_CONF, "Always include REMOTE_USER in the environment, even with an empty value (default true)"),
AP_INIT_TAKE1("uWSGImaxVars", cmd_uwsgi_max_vars, NULL, ACCESS_CONF, "Set the maximum allowed number of uwsgi variables (default 128)"),
{NULL}
};
+7 -3
View File
@@ -1,5 +1,5 @@
[uwsgi]
xml = true
xml = auto
ini = true
yaml = true
json = auto
@@ -15,19 +15,20 @@ threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = auto
pcre = auto
routing = auto
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal
embedded_plugins = python, ping, cache, nagios, rrdtool, carbon, rpc, fastrouter, http, ugreen, signal, syslog, rsyslog, logsocket, router_uwsgi, router_redirect, router_basicauth, zergpool
as_shared_library = false
locking = auto
@@ -35,6 +36,9 @@ event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
+1 -1
View File
@@ -3,7 +3,7 @@ xml = true
ini = true
yaml = true
json = true
sqlite3 = true
sqlite3 = false
zeromq = false
snmp = false
sctp = false
+49
View File
@@ -0,0 +1,49 @@
[uwsgi]
xml = false
ini = true
yaml = false
json = false
sqlite3 = false
zeromq = false
snmp = false
sctp = false
spooler = true
embedded = true
udp = true
multicast = false
threading = true
sendfile = true
minterpreters = true
async = true
evdis = false
ldap = false
pcre = true
routing = true
debug = false
unbit = false
xml_implementation = libxml2
yaml_implementation = auto
malloc_implementation = libc
extras =
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins =
as_shared_library = false
locking = auto
event = auto
timer = auto
filemonitor = auto
blacklist =
whitelist =
embed_files =
embed_config =
[python]
paste = true
web3 = true
+4 -9
View File
@@ -6,12 +6,7 @@ void uwsgi_init_cache() {
int i;
if (!uwsgi.cache_blocksize)
uwsgi.cache_blocksize = UMAX16;
if ((uwsgi.cache_blocksize * uwsgi.cache_max_items) % uwsgi.page_size != 0) {
uwsgi_log("invalid cache blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.cache_blocksize, uwsgi.page_size);
exit(1);
}
uwsgi.cache_blocksize = UMAX16;
uwsgi.cache_hashtable = (uint64_t *) mmap(NULL, sizeof(uint64_t) * UMAX16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (!uwsgi.cache_hashtable) {
@@ -88,10 +83,10 @@ void uwsgi_init_cache() {
uwsgi.cache = ((void *) uwsgi.cache_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items);
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.cache_lock);
uwsgi.cache_lock = uwsgi_rwlock_init("cache");
uwsgi_log("*** Cache subsystem initialized: %dMB preallocated ***\n", ((sizeof(uint64_t) * UMAX16) + (sizeof(uint64_t) * uwsgi.cache_max_items) + (uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024));
uwsgi_log("*** Cache subsystem initialized: %dMB (key: %llu bytes, keys: %llu bytes, data: %llu bytes) preallocated ***\n", ((uwsgi.cache_blocksize * uwsgi.cache_max_items) + (sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items)) / (1024 * 1024),
(unsigned long long) sizeof(struct uwsgi_cache_item), (unsigned long long) sizeof(struct uwsgi_cache_item) * uwsgi.cache_max_items, (unsigned long long) uwsgi.cache_blocksize * uwsgi.cache_max_items);
}
uint32_t djb33x_hash(char *key, int keylen) {
+363
View File
@@ -0,0 +1,363 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
#ifdef UWSGI_UDP
static void cluster_manage_opt(char *key, uint16_t keylen, char *value, uint16_t vallen, void *foobar) {
add_exported_option( uwsgi_concat2n(key, keylen, "", 0), uwsgi_concat2n(value, vallen, "", 0), 0);
}
void cluster_setup() {
int rlen;
// get cluster configuration
if (uwsgi.cluster != NULL) {
// get multicast socket
uwsgi.cluster_fd = uwsgi_cluster_join(uwsgi.cluster);
uwsgi_log("JOINED CLUSTER: %s\n", uwsgi.cluster);
// ask for cluster options only if bot pre-existent options are set
if (uwsgi.exported_opts_cnt == 1 && !uwsgi.cluster_nodes) {
// now wait max 60 seconds and resend multicast request every 10 seconds
for (;;) {
uwsgi_log("asking \"%s\" uWSGI cluster for configuration data:\n", uwsgi.cluster);
if (uwsgi_send_empty_pkt(uwsgi.cluster_fd, uwsgi.cluster, 99, 0) < 0) {
uwsgi_log("unable to send multicast message to %s\n", uwsgi.cluster);
continue;
}
waitfd:
rlen = uwsgi_waitfd(uwsgi.cluster_fd, 10);
if (rlen < 0) {
break;
}
else if (rlen > 0) {
// receive the packet
char clusterbuf[4096];
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
uwsgi_configure(-1);
goto options_parsed;
}
else {
goto waitfd;
}
}
}
}
options_parsed:
if (!uwsgi.cluster_nodes)
uwsgi_cluster_add_me();
}
}
void uwsgi_cluster_add_node(struct uwsgi_cluster_node *nucn, int type) {
int i;
struct uwsgi_cluster_node *ucn;
char *tcp_port;
#ifdef UWSGI_DEBUG
uwsgi_log("adding node\n");
#endif
tcp_port = strchr(nucn->name, ':');
#ifndef UWSGI_ZEROMQ
if (tcp_port == NULL) {
#else
char *zmq_dash = strchr(nucn->name, '-');
if (tcp_port == NULL && zmq_dash == NULL) {
#endif
fprintf(stdout, "invalid cluster node name %s\n", nucn->name);
return;
}
// first check for already present node
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0) {
if (!strcmp(ucn->name, nucn->name)) {
ucn->status = UWSGI_NODE_OK;
ucn->last_seen = time(NULL);
// update requests
ucn->requests = nucn->requests;
return;
}
}
}
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] == 0) {
memcpy(ucn->name, nucn->name, strlen(nucn->name) + 1);
memcpy(ucn->nodename, nucn->nodename, strlen(nucn->nodename) + 1);
ucn->workers = nucn->workers;
ucn->ucn_addr.sin_family = AF_INET;
if (tcp_port) {
ucn->ucn_addr.sin_port = htons(atoi(tcp_port + 1));
tcp_port[0] = 0;
}
if (nucn->name[0] == 0) {
ucn->ucn_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", nucn->name);
#endif
ucn->ucn_addr.sin_addr.s_addr = inet_addr(nucn->name);
}
ucn->type = type;
// here memory can be freed, as it is allocated by uwsgi_concat2n
if (type != CLUSTER_NODE_DYNAMIC && tcp_port) {
tcp_port[0] = ':';
}
ucn->last_seen = time(NULL);
ucn->requests = nucn->requests;
uwsgi_log("[uWSGI cluster] added node %s\n", ucn->name);
return;
}
}
uwsgi_log("unable to add node %s\n", nucn->name);
}
int uwsgi_cluster_add_me() {
const char *key1 = "hostname";
const char *key2 = "address";
const char *key3 = "workers";
const char *key4 = "requests";
char *ptrbuf;
uint16_t ustrlen;
char numproc[6];
#ifdef UWSGI_ZEROMQ
char uuid_zmq_str[37];
uuid_t uuid_zmq;
if (!uwsgi.sockets && !uwsgi.zeromq) {
#else
if (!uwsgi.sockets) {
#endif
uwsgi_log("you need to specify at least a socket to start a uWSGI cluster\n");
exit(1);
}
snprintf(numproc, 6, "%d", uwsgi.numproc);
size_t len;
if (uwsgi.sockets) {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uwsgi.sockets->name) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
uuid_generate(uuid_zmq);
uuid_unparse(uuid_zmq, uuid_zmq_str);
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key2) + 2 + strlen(uuid_zmq_str) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
#endif
else {
len = 2 + strlen(key1) + 2 + strlen(uwsgi.hostname) + 2 + strlen(key3) + 2 + strlen(numproc) + 2 + strlen(key4) + 2 + 1;
}
char *buf = uwsgi_malloc(len);
ptrbuf = buf;
ustrlen = strlen(key1);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key1, strlen(key1));
ptrbuf += strlen(key1);
ustrlen = strlen(uwsgi.hostname);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.hostname, strlen(uwsgi.hostname));
ptrbuf += strlen(uwsgi.hostname);
if (uwsgi.sockets && uwsgi.sockets->name) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uwsgi.sockets->name);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uwsgi.sockets->name, strlen(uwsgi.sockets->name));
ptrbuf += strlen(uwsgi.sockets->name);
}
#ifdef UWSGI_ZEROMQ
else if (uwsgi.zeromq) {
ustrlen = strlen(key2);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key2, strlen(key2));
ptrbuf += strlen(key2);
ustrlen = strlen(uuid_zmq_str);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, uuid_zmq_str, strlen(uuid_zmq_str));
ptrbuf += strlen(uuid_zmq_str);
}
#endif
ustrlen = strlen(key3);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key3, strlen(key3));
ptrbuf += strlen(key3);
ustrlen = strlen(numproc);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, numproc, strlen(numproc));
ptrbuf += strlen(numproc);
ustrlen = strlen(key4);
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, key4, strlen(key4));
ptrbuf += strlen(key4);
ustrlen = 1;
*ptrbuf++ = (uint8_t) (ustrlen & 0xff);
*ptrbuf++ = (uint8_t) ((ustrlen >> 8) & 0xff);
memcpy(ptrbuf, "0", 1);
ptrbuf += 1;
uwsgi_string_sendto(uwsgi.cluster_fd, 95, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), buf, len);
free(buf);
#ifdef UWSGI_DEBUG
uwsgi_log("add_me() successfull\n");
#endif
return 0;
}
int uwsgi_cluster_join(char *name) {
int fd;
char *cp;
int broadcast = 0;
if (name[0] == ':') {
fd = bind_to_udp(name, 0, 1);
broadcast = 1;
}
else {
fd = bind_to_udp(name, 1, 0);
}
if (fd >= 0) {
cp = strchr(name, ':');
cp[0] = 0;
uwsgi.mc_cluster_addr.sin_family = AF_INET;
if (broadcast) {
uwsgi.mc_cluster_addr.sin_addr.s_addr = INADDR_BROADCAST;
}
else {
uwsgi.mc_cluster_addr.sin_addr.s_addr = inet_addr(name);
}
uwsgi.mc_cluster_addr.sin_port = htons(atoi(cp + 1));
cp[0] = ':';
// announce my presence to all the nodes
uwsgi_string_sendto(fd, 73, 0, (struct sockaddr *) &uwsgi.mc_cluster_addr, sizeof(uwsgi.mc_cluster_addr), uwsgi.hostname, strlen(uwsgi.hostname));
}
else {
exit(1);
}
return fd;
}
char *uwsgi_cluster_best_node() {
int i;
int best_node = -1;
struct uwsgi_cluster_node *ucn;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->status == UWSGI_NODE_OK) {
if (best_node == -1) {
best_node = i;
}
else {
if (ucn->last_choosen < uwsgi.shared->nodes[best_node].last_choosen) {
best_node = i;
}
}
}
}
if (best_node == -1) {
return NULL;
}
uwsgi.shared->nodes[best_node].last_choosen = time(NULL);
return uwsgi.shared->nodes[best_node].name;
}
void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
char *tmpstr;
struct uwsgi_cluster_node *ucn = (struct uwsgi_cluster_node *) data;
#ifdef UWSGI_DEBUG
uwsgi_log("%.*s = %.*s\n", keylen, key, vallen, val);
#endif
if (!uwsgi_strncmp("hostname", 8, key, keylen)) {
strncpy(ucn->nodename, val, UMIN(vallen, 255));
}
if (!uwsgi_strncmp("address", 7, key, keylen)) {
strncpy(ucn->name, val, UMIN(vallen, 100));
}
if (!uwsgi_strncmp("workers", 7, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->workers = atoi(tmpstr);
free(tmpstr);
}
if (!uwsgi_strncmp("requests", 8, key, keylen)) {
tmpstr = uwsgi_concat2n(val, vallen, "", 0);
ucn->requests = strtoul(tmpstr, NULL, 0);
free(tmpstr);
}
}
#endif
+53
View File
@@ -0,0 +1,53 @@
#include <Python.h>
void uwsgi_cgi_load_python() {
Py_Initialize();
}
void uwsgi_cgi_run_python(char *filename) {
char **e, *p;
PyObject *k, *env_value;
FILE *fp = fopen(filename, "r");
PySys_SetArgv(1, &filename);
PyObject *os_module = PyImport_ImportModule("os");
if (os_module) {
PyObject *os_module_dict = PyModule_GetDict(os_module);
PyObject *py_environ = PyDict_GetItemString(os_module_dict, "environ");
if (py_environ) {
for (e = environ; *e != NULL; e++) {
p = strchr(*e, '=');
if (p == NULL) continue;
k = PyString_FromStringAndSize(*e, (int)(p-*e));
if (k == NULL) {
PyErr_Print();
continue;
}
env_value = PyString_FromString(p+1);
if (env_value == NULL) {
PyErr_Print();
Py_DECREF(k);
continue;
}
if (PyObject_SetItem(py_environ, k, env_value)) {
PyErr_Print();
}
Py_DECREF(k);
Py_DECREF(env_value);
}
}
}
PyRun_AnyFileEx(fp, filename, 1);
}
+15
View File
@@ -0,0 +1,15 @@
use IO::Socket::INET;
my $s = IO::Socket::INET->new(PeerAddr => '127.0.0.1', PeerPort => $ARGV[0]);
my $mountpoint = $ARGV[1];
my $app = $ARGV[2];
my $uwsgi_appid = pack('v', length('UWSGI_APPID')).'UWSGI_APPID'.pack('v', length($mountpoint)).$mountpoint;
my $uwsgi_script = pack('v', length('UWSGI_SCRIPT')).'UWSGI_SCRIPT'.pack('v', length($app)).$app;
$s->send(pack('CvC', 5, length($uwsgi_appid.$uwsgi_script),0).$uwsgi_appid.$uwsgi_script);
while((my $cnt = $s->recv(my $buf, 4096))> 0) {
print $buf;
}
+21
View File
@@ -0,0 +1,21 @@
#!/bin/bash
COMMAND=./uwsgi
CONFIG_FILE=
FIRST=0
for ARG in $@;do
if [ $FIRST -eq 0 ];then
FIRST=1
else
ARGS="$ARGS $ARG"
fi
done
export UWSGI_INHERIT=CONFIG_FILE
export UWSGI_PYRUN=$1
export UWSGI_PYARGV=$ARGS
exec $COMMAND
+123
View File
@@ -0,0 +1,123 @@
import mmap
import os
import struct
import array
import time
import sys
from optparse import OptionParser
class Cache:
def __init__(self, filename, cache_slots, block_size=65536, sample_sleep=1):
self.block_size = block_size
self.cache_slots = cache_slots
self.key_size = 2048
self.item_size = 2 + 2 + 4 + 8 + 8 + 8 + 8 + 8 + self.key_size
self.block_size_start = self.item_size * self.cache_slots
fd = os.open(filename, os.O_RDONLY)
self.cache_store = mmap.mmap(fd, 0, mmap.MAP_SHARED, mmap.PROT_READ)
self.sample_sleep = sample_sleep
self.samples = 0
self.history = []
self.cache_full = 0
self.cache_empty = 0
self.cache_items = 0
self.block_sizes = 0
def store_read_item_block(self, position):
pos = self.cache_store.tell()
# uwsgi cache stores cache entries first and then the blocks
self.cache_store.seek(self.block_size_start + (position * self.block_size))
buf = self.cache_store.read(self.block_size)
self.cache_store.seek(pos)
return buf
def store_read_item(self, position):
buf = self.cache_store.read(self.item_size)
fields = struct.unpack_from('@HHIQQQQQ2048c', buf)
key = array.array('c', fields[8:self.key_size+8]).tostring().rstrip('\x00')
if [x for x in key if x!= '\x00']:
buf = self.store_read_item_block(position)
value = array.array('c', buf).tostring().rstrip('\x00')
else:
value = ''
return (position, key, value, len(value))
def read(self):
data = [self.store_read_item(i) for i in range(self.cache_slots)]
self.cache_store.seek(0)
self.update_stats(data)
if self.sample_sleep:
time.sleep(self.sample_sleep)
return data
def update_stats(self, data):
# data is a list of (position, key, value, len(value)) tuples
items = len([1 for x in data if x[3] > 0])
self.cache_items += items
full, empty = items == self.cache_slots, items == 0
if full:
self.cache_full += 1
if empty:
self.cache_empty += 1
self.samples += 1
block_sizes = sum([x[3] for x in data])
self.block_sizes += block_sizes
self.history.append({'full': full, 'empty': empty, 'data': data, \
'items': items, 'block_sizes': block_sizes})
def dump(self):
return {
'samples': self.samples,
'history': self.history,
'cache_slots': self.cache_slots,
'sample_sleep': self.sample_sleep,
'cache_empty': self.cache_empty,
'cache_full': self.cache_full,
'cache_items': self.cache_items,
'block_sizes': self.block_sizes,
}
def show_dump(self):
d = self.dump()
print
print "Recorded %d samples (%d second(s) sleep between samples)" % \
(d['samples'], d['sample_sleep'])
print "Cache empty %d times, full %d times, %.2f items on average" % \
(d['cache_empty'], d['cache_full'], d['cache_items'] / d['samples'])
print "Block size average size: %d bytes" % \
(d['block_sizes'] / d['cache_items'] * 8)
print "Data in cache average: %d bytes" % \
(d['block_sizes'] / d['samples'] * 8)
def main(options):
cache = Cache(options.cache_store, options.cache_slots, options.block_size,
options.sleep_time)
print "Recording..."
while True:
try:
data = cache.read()
except KeyboardInterrupt:
cache.show_dump()
sys.exit(0)
if __name__ == '__main__':
parser = OptionParser()
parser.add_option("-s", "--cache-slots", dest="cache_slots", type="int",
help="Slots available in the cache, uwsgi cache option")
parser.add_option("-c", "--cache-store", dest="cache_store", default="uwsgi.cache",
help="The filename of the cache store, uwsgi cache-store option. Default: uwsgi.cache")
parser.add_option("-b", "--block-size", dest="block_size", default=65536, type="int",
help="The size of the cache block, uwsgi cache-blocksize option. Default: 65536")
parser.add_option("-t", "--sleep-time", dest="sleep_time", default=1, type="int",
help="The time to sleep between each sample. Default: 1")
(options, args) = parser.parse_args()
if not options.cache_slots:
parser.error('Option -s / --cache-slots is mandatory')
main(options)
+46 -11
View File
@@ -171,7 +171,7 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
c_ui->respawns++;
c_ui->last_mod = mod;
uwsgi_log("reload the uwsgi instance %s\n", c_ui->name);
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
}
void emperor_add(char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid) {
@@ -314,7 +314,9 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
break;
}
free(oe);
#ifdef UWSGI_DEBUG
uwsgi_log("putenv %s\n", ne);
#endif
if (putenv(ne)) {
uwsgi_error("putenv()");
@@ -334,7 +336,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
}
counter = 4;
struct uwsgi_config_template *uct = uwsgi.vassals_templates;
struct uwsgi_string_list *uct = uwsgi.vassals_templates;
while(uct) {
counter+=2;
uct = uct->next;
@@ -371,14 +373,32 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size, ui
uct = uwsgi.vassals_templates;
while(uct) {
vassal_argv[counter] = "--inherit";
vassal_argv[counter+1] = uct->filename;
vassal_argv[counter+1] = uct->value;
counter+=2;
uct = uct->next;
}
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);
}
if (stdin_fd != 0) {
if (dup2(stdin_fd, 0)) {
uwsgi_error("dup2()");
exit(1);
}
close(stdin_fd);
}
// close all of the unneded fd
for(i=3;i<sysconf(_SC_OPEN_MAX);i++) {
for(i=3;i<(int)uwsgi.max_fd;i++) {
if (n_ui->use_config) {
if (i == n_ui->pipe_config[1])
continue;
}
if (i != n_ui->pipe[1]) {
close(i);
}
@@ -433,6 +453,7 @@ void emperor_loop() {
int nevents;
int interesting_fd;
char notification_message[64];
struct rlimit rl;
uwsgi.emperor_stats_fd = -1;
@@ -444,6 +465,13 @@ void emperor_loop() {
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
if (getrlimit(RLIMIT_NOFILE, &rl)) {
uwsgi_error("getrlimit()");
exit(1);
}
uwsgi.max_fd = rl.rlim_cur;
emperor_queue = event_queue_init();
@@ -512,7 +540,12 @@ reconnect:
uwsgi_error("glob()");
exit(1);
}
emperor_absolute_dir = realpath(".", NULL);
globfree(&g);
emperor_absolute_dir = uwsgi_malloc(PATH_MAX+1);
if (realpath(".", emperor_absolute_dir) == NULL) {
uwsgi_error("realpath()");
exit(1);
}
}
ui = &ui_base;
@@ -614,10 +647,8 @@ reconnect:
}
}
}
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1) {
if (interesting_fd == uwsgi.emperor_stats_fd) {
emperor_send_stats(uwsgi.emperor_stats_fd);
}
else if (uwsgi.emperor_stats && uwsgi.emperor_stats_fd > -1 && interesting_fd == uwsgi.emperor_stats_fd) {
emperor_send_stats(uwsgi.emperor_stats_fd);
}
else {
ui_current = emperor_get_by_fd(interesting_fd);
@@ -626,7 +657,9 @@ reconnect:
ssize_t rlen = read(interesting_fd, &byte, 1);
if (rlen <= 0) {
// SAFE
emperor_del(ui_current);
if (!ui_current->config_len) {
emperor_del(ui_current);
}
}
else {
if (byte == 17) {
@@ -647,7 +680,7 @@ reconnect:
}
}
else {
uwsgi_log("unrecognized event on fd %d\n", interesting_fd);
uwsgi_log("[emperor] unrecognized vassal event on fd %d\n", interesting_fd);
event_queue_del_fd(emperor_queue, interesting_fd, event_queue_read());
close(interesting_fd);
}
@@ -746,6 +779,7 @@ reconnect:
}
}
globfree(&g);
}
}
@@ -847,6 +881,7 @@ void emperor_send_stats(int fd) {
stats_send("{ \"version\": \"%s\",\n", UWSGI_VERSION);
fprintf(output,"\"pid\": %d,\n", (int)(getpid()));
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
+17 -2
View File
@@ -172,6 +172,7 @@ int event_queue_init() {
int epfd;
epfd = epoll_create(256);
if (epfd < 0) {
@@ -403,7 +404,8 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
}
if (ret < 0) {
uwsgi_error("kevent()");
if (errno != EINTR)
uwsgi_error("kevent()");
}
return ret;
@@ -443,7 +445,8 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
}
if (ret < 0) {
uwsgi_error("kevent()");
if (errno != EINTR)
uwsgi_error("kevent()");
}
if (ret > 0) {
@@ -567,6 +570,16 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
#endif
#ifdef UWSGI_EVENT_FILEMONITOR_USE_INOTIFY
#ifdef OBSOLETE_LINUX_KERNEL
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
return -1;
}
struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#else
#include <sys/inotify.h>
int event_queue_add_file_monitor(int eq, char *filename, int *id) {
@@ -659,6 +672,8 @@ struct uwsgi_fmon *event_queue_ack_file_monitor(int eq, int id) {
return NULL;
}
#endif
#endif
#ifdef UWSGI_EVENT_TIMER_USE_TIMERFD
+101 -78
View File
@@ -2,121 +2,76 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_gateway *register_fat_gateway(char *name, void (*loop)(void)) {
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(int)) {
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
if (ushared->gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
for(i=0;i<ushared->gateways_cnt;i++) {
if (!strcmp(name, ushared->gateways[i].name)) {
num++;
}
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
char *fullname = uwsgi_concat3(name, " ", uwsgi_num2str(num));
ug = &ushared->gateways[ushared->gateways_cnt];
ug->pid = 0;
ug->name = name;
ug->loop = loop;
ug->num = num;
ug->fullname = fullname;
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, ug->internal_subscription_pipe)) {
uwsgi_error("socketpair()");
}
if (!uwsgi.master_process)
gateway_respawn(ushared->gateways_cnt);
ushared->gateways_cnt++;
uwsgi.gateways_cnt++;
return ug;
}
struct uwsgi_gateway *register_gateway(char *name, void (*loop)(void)) {
pid_t gw_pid;
pid_t orig_pid = getpid();
struct uwsgi_gateway *ug;
int num=1,i;
if (uwsgi.gateways_cnt >= MAX_GATEWAYS) {
uwsgi_log("you can register max %d gateways\n", MAX_GATEWAYS);
return NULL;
}
for(i=0;i<uwsgi.gateways_cnt;i++) {
if (!strcmp(name, uwsgi.gateways[i].name)) {
num++;
}
}
gw_pid = uwsgi_fork(name);
if (gw_pid < 0) {
uwsgi_error("fork()");
return NULL;
}
if (!uwsgi.master_process) {
if (gw_pid > 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
if (!uwsgi.sockets) {
// wait for child end
//waitpid(-1, &i, 0);
}
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = orig_pid;
}
else {
if (gw_pid == 0) {
if (uwsgi.master_as_root) uwsgi_as_root();
loop();
// never here !!! (i hope)
exit(1);
}
ug = &uwsgi.gateways[uwsgi.gateways_cnt];
ug->pid = gw_pid;
}
ug->name = name;
ug->loop = loop;
ug->num = num;
uwsgi_log( "spawned %s %d (pid: %d)\n", ug->name, ug->num, (int) ug->pid);
uwsgi.gateways_cnt++;
return ug;
}
void gateway_respawn(int id) {
pid_t gw_pid;
struct uwsgi_gateway *ug = &uwsgi.gateways[id];
struct uwsgi_gateway *ug = &ushared->gateways[id];
if (uwsgi.master_process)
uwsgi.shared->gateways_harakiri[id] = 0;
gw_pid = uwsgi_fork(ug->name);
gw_pid = uwsgi_fork(ug->fullname);
if (gw_pid < 0) {
uwsgi_error("fork()");
return;
}
if (gw_pid == 0) {
uwsgi_fixup_fds(0, 0, ug);
if (uwsgi.master_as_root) uwsgi_as_root();
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0,0,0)) {
uwsgi_error("prctl()");
}
#endif
ug->loop();
uwsgi.mypid = getpid();
signal(SIGALRM, SIG_IGN);
signal(SIGHUP, SIG_IGN);
signal(SIGINT, end_me);
signal(SIGTERM, end_me);
signal(SIGUSR1, SIG_IGN);
signal(SIGUSR2, SIG_IGN);
signal(SIGPIPE, SIG_IGN);
ug->loop(id);
// never here !!! (i hope)
exit(1);
}
@@ -131,3 +86,71 @@ void gateway_respawn(int id) {
}
}
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket(char *name, char *owner) {
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = -1;
uwsgi_sock->shared = 0;
uwsgi_sock->name = name;
uwsgi_sock->owner = owner;
return uwsgi_sock;
}
struct uwsgi_gateway_socket *uwsgi_new_gateway_socket_from_fd(int fd, char *owner) {
struct uwsgi_gateway_socket *uwsgi_sock = uwsgi.gateway_sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
uwsgi.gateway_sockets = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
uwsgi_sock = uwsgi.gateway_sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_gateway_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_gateway_socket));
uwsgi_sock->fd = fd;
uwsgi_sock->name = uwsgi_getsockname(fd);
uwsgi_sock->owner = owner;
return uwsgi_sock;
}
void uwsgi_gateway_go_cheap(char *gw_id, int queue, int *i_am_cheap) {
uwsgi_log("[%s pid %d] no more nodes available. Going cheap...\n", gw_id, (int) uwsgi.mypid);
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
event_queue_del_fd(queue, ugs->fd, event_queue_read());
}
ugs = ugs->next;
}
*i_am_cheap = 1;
}
+1
View File
@@ -2,5 +2,6 @@ import uwsgi
#uwsgi.cache_set('/', "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\nHello World from cache")
def application(env, start_response):
start_response('200 OK', [('Content-Type', 'text/html')])
yield "foobar"
yield str(env['wsgi.input'].fileno())
yield "<h1>Hello World</h1>"
+25
View File
@@ -0,0 +1,25 @@
uWSGI version <b><?=uwsgi_version()?></b><br/>
workerd id: <b><?=uwsgi_worker_id()?></b><br/>
master pid: <b><?=uwsgi_masterpid()?></b><br/>
uri: <b><?= $_SERVER['REQUEST_URI'] ?></b><br/>
docroot: <b><?= $_SERVER['DOCUMENT_ROOT'] ?></b><br/>
PATH_INFO: <b><?= $_SERVER['PATH_INFO'] ?></b><br/>
<? uwsgi_signal(17) ?>
<? uwsgi_setprocname("test test test"); ?>
rpc result:<br/>
<? echo uwsgi_rpc("", "hello", "one", "two", "three"); ?>
<?
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
uwsgi_cache_update('foobar', $_POST['cache_val']);
}
?>
<form method="POST">
<input type="text" name="cache_val" value="<?=uwsgi_cache_get('foobar')?>"/>
<input type="submit" value="cache set" />
</form>
+2 -2
View File
@@ -14,7 +14,7 @@ void ini_rstrip(char *line) {
off_t i;
for(i = strlen(line)-1;i>=0; i--) {
if (line[i] == ' ' || line[i] == '\t') {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
line[i] = 0;
continue;
}
@@ -28,7 +28,7 @@ char *ini_lstrip(char *line) {
char *ptr = line;
for(i=0;i< (int) strlen(line);i++) {
if (line[i] == ' ' || line[i] == '\t') {
if (line[i] == ' ' || line[i] == '\t' || line[i] == '\r') {
ptr++;
continue;
}
+13 -37
View File
@@ -108,56 +108,37 @@ struct uwsgi_ldap_entry *search_ldap_cache(struct uwsgi_ldap_entry *root, char *
struct uwsgi_ldap_entry *get_ldap_names(int *count) {
struct option *aopt, *lopt;
struct uwsgi_option *op = uwsgi.options;
struct uwsgi_ldap_entry *ule, *entry;
char ldap_name[1024];
static int counter = 30000000;
*count = 0;
lopt = uwsgi.long_options;
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*count_options(lopt));
ule = uwsgi_malloc(sizeof(struct uwsgi_ldap_entry)*uwsgi_count_options(op));
while( (aopt = lopt) ) {
if (!aopt->name)
break;
while( op && op->name ) {
uwsgi_name_to_ldap((char *)aopt->name, ldap_name);
uwsgi_name_to_ldap((char *)op->name, ldap_name);
entry = search_ldap_cache(ule, ldap_name, *count);
if (entry) goto next;
if (aopt->flag) {
entry = &ule[*count] ;
entry->num = counter;
strcpy(entry->names, ldap_name);
counter++;
*count = *count+1;
}
else {
entry = get_ldap_by_num(ule, aopt->val, *count);
if (entry) {
strcat(entry->names, ldap_name);
}
else {
entry = &ule[*count] ;
entry->num = aopt->val;
strcpy(entry->names, ldap_name);
*count = *count+1;
}
}
entry = &ule[*count] ;
entry->num = *count;
strcpy(entry->names, ldap_name);
*count = *count+1;
entry->has_arg = aopt->has_arg;
entry->has_arg = op->type;
next:
lopt++;
op++;
}
return ule;
}
void uwsgi_ldap_schema_dump_ldif() {
void uwsgi_opt_ldap_dump_ldif(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -210,7 +191,7 @@ void uwsgi_ldap_schema_dump_ldif() {
exit(0);
}
void uwsgi_ldap_schema_dump() {
void uwsgi_opt_ldap_dump(char *opt, char *foo, void *bar) {
int i;
int items;
@@ -258,7 +239,7 @@ void uwsgi_ldap_schema_dump() {
exit(0);
}
void uwsgi_ldap_config() {
void uwsgi_ldap_config(char *url) {
LDAP *ldp;
LDAPMessage *results, *entry;
@@ -267,7 +248,6 @@ void uwsgi_ldap_config() {
char *attr;
char *uwsgi_attr;
char *url = "ldap:///";
char *url_slash;
int desired_version = LDAP_VERSION3;
@@ -275,10 +255,6 @@ void uwsgi_ldap_config() {
LDAPURLDesc *ldap_url;
if (uwsgi.ldap) {
url = uwsgi.ldap;
}
if (!ldap_is_ldap_url(url)) {
uwsgi_log("invalid LDAP url.\n");
exit(1);
+3 -34
View File
@@ -27,22 +27,6 @@ struct amqp_frame_method {
static char *amqp_simple_get_frame(int, struct amqp_frame_header *);
static char *amqp_get_method(int, uint16_t, uint16_t, uint32_t *);
/*
static char *amqp_get_longstr(char *ptr, char *watermark) {
uint32_t longstr_size;
if (ptr+4 > watermark) return NULL;
memcpy(&longstr_size, ptr, 4);
longstr_size = ntohl(longstr_size);
if (ptr+4+longstr_size > watermark) return NULL;
return ptr+4+longstr_size;
}
*/
static char *amqp_get_str(char *ptr, char *watermark) {
uint8_t str_size;
@@ -58,23 +42,6 @@ static char *amqp_get_str(char *ptr, char *watermark) {
}
/*
static char *amqp_get_table(char *ptr, char *watermark) {
uint32_t table_size;
if (ptr+4 > watermark) return NULL;
memcpy(&table_size, ptr, 4);
table_size = ntohl(table_size);
if (ptr+4+table_size > watermark) return NULL;
return ptr+4+table_size;
}
*/
static char *amqp_get_short(char *ptr, char *watermark, uint16_t *sv) {
uint16_t tmp_short;
@@ -197,7 +164,9 @@ char *uwsgi_amqp_consume(int fd, uint64_t *msgsize, char **routing_key) {
ptr = amqp_get_longlong(ptr, watermark, msgsize); if (!ptr) goto clear2;
free(frame);
frame = NULL;
free(header);
header = NULL;
char *fullbody = uwsgi_malloc(*msgsize);
char *message;
@@ -501,7 +470,7 @@ static char *amqp_simple_get_frame(int fd, struct amqp_frame_header *fh) {
len = 0;
char *frame = malloc(fh->size+1);
char *frame = uwsgi_malloc(fh->size+1);
ptr = frame;
while(len < fh->size+1) {
+202
View File
@@ -0,0 +1,202 @@
/*
common functions for various routers (fastrouter, http...)
*/
static void uwsgi_corerouter_setup_sockets(char *gw_id) {
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(gw_id, ugs->owner)) {
#ifdef UWSGI_SCTP
if (!ugs->subscription && !ugs->sctp) {
#else
if (!ugs->subscription) {
#endif
if (ugs->name[0] == '=') {
int shared_socket = atoi(ugs->name+1);
if (shared_socket >= 0) {
ugs->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
ugs->shared = 1;
if (ugs->fd == -1) {
uwsgi_log("unable to use shared socket %d\n", shared_socket);
exit(1);
}
ugs->name = uwsgi_getsockname(ugs->fd);
}
}
else if (!uwsgi_startswith("fd://", ugs->name, 5 )) {
int fd_socket = atoi(ugs->name+5);
if (fd_socket >= 0) {
ugs->fd = fd_socket;
ugs->name = uwsgi_getsockname(ugs->fd);
if (!ugs->name) {
uwsgi_log("unable to use file descriptor %d as socket\n", fd_socket);
exit(1);
}
}
}
else {
ugs->port = strchr(ugs->name, ':');
if (ugs->fd == -1) {
if (ugs->port) {
ugs->fd = bind_to_tcp(ugs->name, uwsgi.listen_queue, ugs->port);
ugs->port++;
ugs->port_len = strlen(ugs->port);
}
else {
ugs->fd = bind_to_unix(ugs->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
}
}
// put socket in non-blocking mode
uwsgi_socket_nb(ugs->fd);
uwsgi_log("%s bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
}
else if (ugs->subscription) {
if (ugs->fd == -1) {
ugs->fd = bind_to_udp(ugs->name, 0, 0);
uwsgi_socket_nb(ugs->fd);
}
uwsgi_log("%s subscription server bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
}
#ifdef UWSGI_SCTP
else if (ugs->sctp) {
if (ugs->fd == -1) {
ugs->fd = bind_to_sctp(ugs->name);
}
uwsgi_log("%s SCTP server bound on %s fd %d\n", gw_id, ugs->name, ugs->fd);
}
#endif
}
ugs = ugs->next;
}
}
static void *uwsgi_corerouter_setup_event_queue(char *gw_id, int id, int nevents, int *efd, int cheap) {
*efd = event_queue_init();
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(gw_id, ugs->owner)) {
if (!cheap || ugs->subscription) {
event_queue_add_fd_read(*efd, ugs->fd);
}
ugs->gateway = &ushared->gateways[id];
}
ugs = ugs->next;
}
return event_queue_alloc(nevents);
}
static void __attribute__ ((unused)) uwsgi_corerouter_manage_subscription(char *gw_id, int id, struct uwsgi_gateway_socket *ugs, int queue, struct uwsgi_subscribe_slot **subscriptions, int regexp, void (*parse_hook) (char *, uint16_t, char *, uint16_t, void *), int cheap, int *i_am_cheap) {
int i;
struct uwsgi_subscribe_req usr;
char bbuf[4096];
ssize_t len = recv(ugs->fd, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(queue, ugs->fd);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf + 4, len - 4, parse_hook, &usr);
// subscribe request ?
if (bbuf[3] == 0) {
if (uwsgi_add_subscribe_node(subscriptions, &usr, regexp) && *i_am_cheap) {
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
event_queue_add_fd_read(queue, ugs->fd);
}
ugs = ugs->next;
}
*i_am_cheap = 0;
uwsgi_log("[%s pid %d] leaving cheap mode...\n", gw_id, (int) uwsgi.mypid);
}
}
//unsubscribe
else {
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, regexp);
if (node && node->len) {
if (node->death_mark == 0)
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", gw_id, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
node->failcnt++;
node->death_mark = 1;
// check if i can remove the node
if (node->reference == 0) {
uwsgi_remove_subscribe_node(subscriptions, node);
}
if (*subscriptions == NULL && cheap && !*i_am_cheap) {
uwsgi_gateway_go_cheap(gw_id, queue, i_am_cheap);
}
}
}
// propagate the subscription to other nodes
for (i = 0; i < ushared->gateways_cnt; i++) {
if (i == id)
continue;
if (!strcmp(ushared->gateways[i].name, gw_id)) {
if (send(ushared->gateways[i].internal_subscription_pipe[0], bbuf, len, 0) != len) {
uwsgi_error("send()");
}
}
}
}
}
static void __attribute__ ((unused)) uwsgi_corerouter_manage_internal_subscription(char *gw_id, int queue, int fd, struct uwsgi_subscribe_slot **subscriptions, int regexp, void (*parse_hook) (char *, uint16_t, char *, uint16_t, void *), int cheap, int *i_am_cheap) {
struct uwsgi_subscribe_req usr;
char bbuf[4096];
ssize_t len = recv(fd, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(queue, fd);
#endif
if (len > 0) {
memset(&usr, 0, sizeof(struct uwsgi_subscribe_req));
uwsgi_hooked_parse(bbuf + 4, len - 4, parse_hook, &usr);
// subscribe request ?
if (bbuf[3] == 0) {
if (uwsgi_add_subscribe_node(subscriptions, &usr, regexp) && *i_am_cheap) {
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (!strcmp(ugs->owner, gw_id) && !ugs->subscription) {
event_queue_add_fd_read(queue, ugs->fd);
}
ugs = ugs->next;
}
*i_am_cheap = 0;
uwsgi_log("[%s pid %d] leaving cheap mode...\n", gw_id, (int) uwsgi.mypid);
}
}
//unsubscribe
else {
struct uwsgi_subscribe_node *node = uwsgi_get_subscribe_node_by_name(subscriptions, usr.key, usr.keylen, usr.address, usr.address_len, regexp);
if (node && node->len) {
if (node->death_mark == 0)
uwsgi_log("[%s pid %d] %.*s => marking %.*s as failed\n", gw_id, (int) uwsgi.mypid, (int) usr.keylen, usr.key, (int) usr.address_len, usr.address);
node->failcnt++;
node->death_mark = 1;
// check if i can remove the node
if (node->reference == 0) {
uwsgi_remove_subscribe_node(subscriptions, node);
}
if (*subscriptions == NULL && cheap && !*i_am_cheap) {
uwsgi_gateway_go_cheap(gw_id, queue, i_am_cheap);
}
}
}
}
}
+16
View File
@@ -33,6 +33,22 @@ void linux_namespace_start(void *argv) {
uwsgi_error("clone()");
exit(1);
}
// run the post-jail scripts
if (setenv("UWSGI_JAIL_PID", uwsgi_num2str((int) pid), 1)) {
uwsgi_error("setenv()");
}
struct uwsgi_string_list *usl = uwsgi.exec_post_jail;
while(usl) {
uwsgi_log("running \"%s\" (post-jail)...\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;
}
uwsgi_log("waiting for jailed master (pid: %d) death...\n", (int) pid);
pid = waitpid(pid, &waitpid_status, 0);
if (pid < 0) {
+15
View File
@@ -1,5 +1,20 @@
#include "../uwsgi.h"
#ifdef OBSOLETE_LINUX_KERNEL
#ifndef __u16
#define __u16 u_int16_t
#endif
#ifndef __u32
#define __u32 u_int32_t
#endif
#ifndef __s32
#define __s32 int32_t
#endif
#ifndef __u8
#define __u8 u_int8_t
#endif
#endif
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
+386 -95
View File
@@ -1,196 +1,487 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
static struct uwsgi_lock_item *uwsgi_register_lock(char *id, int rw) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uli) {
uwsgi.registered_locks = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
uwsgi.registered_locks->id = id;
uwsgi.registered_locks->pid = 0;
if (rw) {
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
}
else {
uwsgi.registered_locks->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
}
uwsgi.registered_locks->rw = rw;
uwsgi.registered_locks->next = NULL;
return uwsgi.registered_locks;
}
while(uli) {
if (!uli->next) {
uli->next = uwsgi_malloc_shared(sizeof(struct uwsgi_lock_item));
if (rw) {
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.rwlock_size);
}
else {
uli->next->lock_ptr = uwsgi_malloc_shared(uwsgi.lock_size);
}
uli->next->id = id;
uli->next->pid = 0;
uli->next->rw = rw;
uli->next->next = NULL;
return uli->next;
}
uli = uli->next;
}
uwsgi_log("*** DANGER: unable to allocate lock %s ***\n", id);
exit(1);
}
#ifdef UWSGI_LOCK_USE_MUTEX
#define UWSGI_LOCK_SIZE sizeof(pthread_mutexattr_t) + sizeof(pthread_mutex_t)
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlockattr_t) + sizeof(pthread_rwlock_t)
#define UWSGI_LOCK_ENGINE_NAME "pthread mutexes"
#define UWSGI_LOCK_SIZE sizeof(pthread_mutex_t)
#ifdef OBSOLETE_LINUX_KERNEL
#define UWSGI_RWLOCK_SIZE sizeof(pthread_mutex_t)
#else
#define UWSGI_RWLOCK_SIZE sizeof(pthread_rwlock_t)
#endif
// REMEMBER lock must contains space for both pthread_mutex_t and pthread_mutexattr_t !!!
void uwsgi_lock_init(void *lock) {
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
if (pthread_mutexattr_init((pthread_mutexattr_t *) lock)) {
pthread_mutexattr_t attr;
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
if (pthread_mutexattr_init(&attr)) {
uwsgi_log("unable to allocate mutexattr structure\n");
exit(1);
}
if (pthread_mutexattr_setpshared((pthread_mutexattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
if (pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share mutex\n");
exit(1);
}
if (pthread_mutex_init((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t), (pthread_mutexattr_t *) lock)) {
if (pthread_mutex_init((pthread_mutex_t *) uli->lock_ptr, &attr)) {
uwsgi_log("unable to initialize mutex\n");
exit(1);
}
pthread_mutexattr_destroy(&attr);
uli->can_deadlock = 1;
return uli;
}
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (pthread_mutex_trylock((pthread_mutex_t *) uli->lock_ptr) == 0 ) {
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
return uwsgi_lock_fast_check(uli);
#else
if (pthread_rwlock_trywrlock((pthread_rwlock_t *) uli->lock_ptr) == 0 ) {
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
return 0;
}
return uli->pid;
#endif
}
void uwsgi_rlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock_fast(uli);
#else
pthread_rwlock_rdlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
#endif
}
void uwsgi_wlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_lock_fast(uli);
#else
pthread_rwlock_wrlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
#endif
}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) {
#ifdef OBSOLETE_LINUX_KERNEL
uwsgi_unlock_fast(uli);
#else
pthread_rwlock_unlock((pthread_rwlock_t *) uli->lock_ptr);
uli->pid = 0;
#endif
}
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
pthread_mutex_lock((pthread_mutex_t *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
pthread_mutex_unlock((pthread_mutex_t *) uli->lock_ptr);
uli->pid = 0;
}
void uwsgi_rlock(void *lock) {
pthread_rwlock_rdlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
void uwsgi_wlock(void *lock) {
pthread_rwlock_wrlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
}
#ifdef OBSOLETE_LINUX_KERNEL
return uwsgi_lock_fast_init(uli);
#else
void uwsgi_rwunlock(void *lock) {
pthread_rwlock_unlock((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t));
}
pthread_rwlockattr_t attr;
void uwsgi_lock(void *lock) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
pthread_mutex_lock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
void uwsgi_unlock(void *lock) {
pthread_mutex_unlock((pthread_mutex_t *) lock + sizeof(pthread_mutexattr_t));
}
void uwsgi_rwlock_init(void *lock) {
if (pthread_rwlockattr_init((pthread_rwlockattr_t *) lock)) {
if (pthread_rwlockattr_init(&attr)) {
uwsgi_log("unable to allocate rwlock structure\n");
exit(1);
}
if (pthread_rwlockattr_setpshared((pthread_rwlockattr_t *) lock, PTHREAD_PROCESS_SHARED)) {
if (pthread_rwlockattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) {
uwsgi_log("unable to share rwlock\n");
exit(1);
}
if (pthread_rwlock_init((pthread_rwlock_t *) lock + sizeof(pthread_rwlockattr_t), (pthread_rwlockattr_t *) lock)) {
if (pthread_rwlock_init((pthread_rwlock_t *) uli->lock_ptr, &attr)) {
uwsgi_log("unable to initialize rwlock\n");
exit(1);
}
pthread_rwlockattr_destroy(&attr);
uli->can_deadlock = 1;
return uli;
#endif
}
#endif
#elif defined(UWSGI_LOCK_USE_UMTX)
#ifdef UWSGI_LOCK_USE_UMTX
/* Warning: FreeBSD is still not ready for process-shared UMTX */
#include <machine/atomic.h>
#include <sys/umtx.h>
#define UWSGI_LOCK_SIZE sizeof(struct umtx)
#define UWSGI_RWLOCK_SIZE sizeof(struct umtx)
#define UWSGI_LOCK_ENGINE_NAME "FreeBSD umtx"
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
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);}
void uwsgi_rwunlock_fast(struct uwsgi_lock_item *uli) { uwsgi_unlock_fast(uli); }
void uwsgi_lock_init(void *lock) {
umtx_init((struct umtx*) lock);
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
umtx_init((struct umtx*) uli->lock_ptr);
return uli;
}
void uwsgi_lock(void *lock) {
umtx_lock(lock, 1);
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
umtx_lock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock(void *lock) {
umtx_unlock(lock, 1);
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
uli->pid = 0;
}
#endif
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (umtx_trylock((struct umtx*) uli->lock_ptr, (u_long) getpid() )) {
umtx_unlock((struct umtx*) uli->lock_ptr, (u_long) getpid() );
return 0;
}
return uli->pid;
}
pid_t uwsgi_rwlock_fast_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_fast_check(uli); }
#ifdef UWSGI_LOCK_USE_OSX_SPINLOCK
#elif defined(UWSGI_LOCK_USE_OSX_SPINLOCK)
#define UWSGI_LOCK_ENGINE_NAME "OSX spinlocks"
#define UWSGI_LOCK_SIZE sizeof(OSSpinLock)
#define UWSGI_RWLOCK_SIZE sizeof(OSSpinLock)
void uwsgi_lock_init(void *lock) {
struct uwsgi_lock_item *uwsgi_lock_fast_init(char *id) {
memset(lock, 0, sizeof(OSSpinLock));
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
uli->can_deadlock = 1;
return uli;
}
void uwsgi_lock(void *lock) {
void uwsgi_lock_fast(struct uwsgi_lock_item *uli) {
OSSpinLockLock((OSSpinLock *) lock);
OSSpinLockLock((OSSpinLock *) uli->lock_ptr);
uli->pid = uwsgi.mypid;
}
void uwsgi_unlock(void *lock) {
void uwsgi_unlock_fast(struct uwsgi_lock_item *uli) {
OSSpinLockUnlock((OSSpinLock *) lock);
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
uli->pid = 0;
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
pid_t uwsgi_lock_fast_check(struct uwsgi_lock_item *uli) {
if (OSSpinLockTry((OSSpinLock *) uli->lock_ptr)) {
OSSpinLockUnlock((OSSpinLock *) uli->lock_ptr);
return 0;
}
return uli->pid;
}
struct uwsgi_lock_item *uwsgi_rwlock_fast_init(char *id) {
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 1);
memset(uli->lock_ptr, 0, UWSGI_LOCK_SIZE);
uli->can_deadlock = 1;
return uli;
}
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
#define uwsgi_lock_fast_check uwsgi_lock_ipcsem_check
#define uwsgi_lock_fast uwsgi_lock_ipcsem
#define uwsgi_unlock_fast uwsgi_unlock_ipcsem
#define uwsgi_rwlock_fast_init uwsgi_rwlock_ipcsem_init
#define uwsgi_rwlock_fast_check uwsgi_rwlock_ipcsem_check
#define uwsgi_rlock_fast uwsgi_rlock_ipcsem
#define uwsgi_wlock_fast uwsgi_wlock_ipcsem
#define uwsgi_rwunlock_fast uwsgi_rwunlock_ipcsem
#define UWSGI_LOCK_SIZE sizeof(int)
#define UWSGI_RWLOCK_SIZE sizeof(int)
#define UWSGI_LOCK_ENGINE_NAME "ipcsem"
#define UWSGI_IPCSEM_ATEXIT 1
#endif
struct uwsgi_lock_item *uwsgi_lock_ipcsem_init(char *id) {
#ifdef UWSGI_LOCK_USE_FLOCK
// used by ftok
static int counter = 1;
union semun {
int val;
struct semid_ds *buf;
ushort *array;
} semu ;
int semid;
key_t myKey;
#define UWSGI_LOCK_SIZE 8
#define UWSGI_RWLOCK_SIZE 8
struct uwsgi_lock_item *uli = uwsgi_register_lock(id, 0);
void uwsgi_lock_init(void *lock) {
if (uwsgi.ftok) {
myKey = ftok(uwsgi.ftok, counter);
if (myKey < 0) {
uwsgi_error("ftok()");
exit(1);
}
counter++;
semid = semget(myKey, 1, IPC_CREAT|0666);
}
else {
semid = semget(IPC_PRIVATE, 1, IPC_CREAT|IPC_EXCL| 0666);
}
FILE *tf = tmpfile();
int fd;
if (semid < 0) {
uwsgi_error("semget()");
exit(1);
}
// do this now, to allows triggering of atexit hook in case of problems
memcpy(uli->lock_ptr, &semid, sizeof(int));
if (!tf) {
uwsgi_error_open("temp lock file");
semu.val = 1;
if (semctl(semid, 0, SETVAL, semu)) {
uwsgi_error("semctl()");
exit(1);
}
fd = fileno(tf);
memcpy(lock, &fd, sizeof(int));
return uli;
}
void uwsgi_lock(void *lock) {
void uwsgi_lock_ipcsem(struct uwsgi_lock_item *uli) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_EX)) { uwsgi_error("flock()"); }
int semid;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = -1;
sb.sem_flg = SEM_UNDO;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semop(semid, &sb, 1)) {
uwsgi_error("semop()");
}
}
void uwsgi_unlock(void *lock) {
int fd;
memcpy(&fd, lock, sizeof(int));
if (flock(fd, LOCK_UN)) { uwsgi_error("flock()"); }
void uwsgi_unlock_ipcsem(struct uwsgi_lock_item *uli) {
int semid;
struct sembuf sb;
sb.sem_num = 0;
sb.sem_op = 1;
sb.sem_flg = SEM_UNDO;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semop(semid, &sb, 1)) {
uwsgi_error("semop()");
}
}
void uwsgi_rwlock_init(void *lock) { uwsgi_lock_init(lock) ;}
void uwsgi_rlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_wlock(void *lock) { uwsgi_lock(lock);}
void uwsgi_rwunlock(void *lock) { uwsgi_unlock(lock); }
struct uwsgi_lock_item *uwsgi_rwlock_ipcsem_init(char *id) { return uwsgi_lock_ipcsem_init(id);}
void uwsgi_rlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
void uwsgi_wlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_lock_ipcsem(uli);}
void uwsgi_rwunlock_ipcsem(struct uwsgi_lock_item *uli) { uwsgi_unlock_ipcsem(uli); }
// ipc cannot deadlock
pid_t uwsgi_lock_ipcsem_check(struct uwsgi_lock_item *uli) {
return 0;
}
void uwsgi_ipcsem_clear(void) {
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
if (!uwsgi.workers) goto clear;
if (uwsgi.mywid == 0) goto clear;
if (uwsgi.master_process && getpid() == uwsgi.workers[0].pid) goto clear;
if (!uwsgi.master_process && uwsgi.mywid == 1) goto clear;
return;
clear:
#ifdef UWSGI_DEBUG
uwsgi_log("removing sysvipc semaphores...\n");
#endif
void *uwsgi_mmap_shared_lock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_LOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
while(uli) {
int semid = 0;
memcpy(&semid, uli->lock_ptr, sizeof(int));
if (semctl(semid, 0, IPC_RMID)) {
uwsgi_error("semctl()");
}
uli = uli->next;
}
return addr;
}
void *uwsgi_mmap_shared_rwlock() {
void *addr = NULL;
addr = mmap(NULL, UWSGI_RWLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (addr == NULL) {
uwsgi_error("mmap()");
exit(1);
pid_t uwsgi_rwlock_ipcsem_check(struct uwsgi_lock_item *uli) { return uwsgi_lock_ipcsem_check(uli); }
void uwsgi_setup_locking() {
// use the fastest avaikable locking
if (uwsgi.lock_engine) {
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
uwsgi_log("lock engine: ipcsem\n");
atexit(uwsgi_ipcsem_clear);
uwsgi.lock_ops.lock_init = uwsgi_lock_ipcsem_init;
uwsgi.lock_ops.lock_check = uwsgi_lock_ipcsem_check;
uwsgi.lock_ops.lock = uwsgi_lock_ipcsem;
uwsgi.lock_ops.unlock = uwsgi_unlock_ipcsem;
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_ipcsem_init;
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_ipcsem_check;
uwsgi.lock_ops.rlock = uwsgi_rlock_ipcsem;
uwsgi.lock_ops.wlock = uwsgi_wlock_ipcsem;
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
uwsgi.lock_size = 8;
uwsgi.rwlock_size = 8;
return;
}
}
return addr;
uwsgi_log("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
#ifdef UWSGI_IPCSEM_ATEXIT
atexit(uwsgi_ipcsem_clear);
#endif
uwsgi.lock_ops.lock_init = uwsgi_lock_fast_init;
uwsgi.lock_ops.lock_check = uwsgi_lock_fast_check;
uwsgi.lock_ops.lock = uwsgi_lock_fast;
uwsgi.lock_ops.unlock = uwsgi_unlock_fast;
uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_fast_init;
uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_fast_check;
uwsgi.lock_ops.rlock = uwsgi_rlock_fast;
uwsgi.lock_ops.wlock = uwsgi_wlock_fast;
uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_fast;
uwsgi.lock_size = UWSGI_LOCK_SIZE;
uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;
}
int uwsgi_fcntl_lock(int fd) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_CUR;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
int ret = fcntl(fd, F_SETLKW, &fl);
if (ret < 0)
uwsgi_error("fcntl()");
return ret;
}
int uwsgi_fcntl_is_locked(int fd) {
struct flock fl;
fl.l_type = F_WRLCK;
fl.l_whence = SEEK_CUR;
fl.l_start = 0;
fl.l_len = 0;
fl.l_pid = 0;
if (fcntl(fd, F_SETLK, &fl)) {
return 1;
}
return 0;
}
+148 -34
View File
@@ -19,6 +19,97 @@
extern struct uwsgi_server uwsgi;
void uwsgi_check_logrotate(void) {
char message[1024];
int need_rotation = 0;
int need_reopen = 0;
if (uwsgi.log_master) {
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
}
else {
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
}
if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
need_rotation = 1;
}
if (uwsgi_check_touches(uwsgi.touch_logrotate)) {
need_rotation = 1;
}
if (uwsgi_check_touches(uwsgi.touch_logreopen)) {
need_reopen = 1;
}
if (need_rotation) {
char *rot_name = uwsgi.log_backupname;
int need_free = 0;
if (rot_name == NULL) {
char *ts_str = uwsgi_num2str((int) time(NULL));
rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
free(ts_str);
need_free = 1;
}
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize, rot_name);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
if (rename(uwsgi.logfile, rot_name) == 0) {
// reopen logfile dup'it and eventually gracefully reload workers;
int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
if (fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
if (dup2(fd, uwsgi.original_log_fd) < 0) {
uwsgi_error("dup2()");
grace_them_all(0);
}
close(fd);
}
else {
uwsgi_error("unable to rotate log: rename()");
}
if (need_free)
free(rot_name);
}
else if (need_reopen) {
int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) time(NULL), (unsigned long long) uwsgi.shared->logsize);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
// reopen logfile;
close(uwsgi.original_log_fd);
uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
if (uwsgi.original_log_fd < 0) {
uwsgi_error_open(uwsgi.logfile);
grace_them_all(0);
}
ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) time(NULL), uwsgi.logfile);
if (ret > 0) {
if (write(uwsgi.original_log_fd, message, ret) != ret) {
// very probably this will never be printed
uwsgi_error("write()");
}
}
uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
}
}
void log_request(struct wsgi_request *wsgi_req) {
// optimize this (please)
@@ -48,7 +139,8 @@ void log_request(struct wsgi_request *wsgi_req) {
struct uwsgi_app *wi;
if (wsgi_req->do_not_log) return ;
if (wsgi_req->do_not_log)
return;
if (wsgi_req->app_id >= 0) {
wi = &uwsgi_apps[wsgi_req->app_id];
@@ -58,13 +150,13 @@ void log_request(struct wsgi_request *wsgi_req) {
}
#ifdef UWSGI_SENDFILE
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
if (wsgi_req->sendfile_fd > -1 && wsgi_req->sendfile_obj == wsgi_req->async_result) { //wsgi_req->sendfile_fd_size > 0 ) {
via = msg1;
}
#endif
// mark route() requests
if (wsgi_req->status == -1) {
if (wsgi_req->status == -17) {
via = msg3;
}
@@ -93,12 +185,9 @@ void log_request(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);
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);
rlen = snprintf(mempkt, 4096, "{address space usage: %lld bytes/%lluMB} ", (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size, (unsigned long long) uwsgi.workers[uwsgi.mywid].vsz_size / 1024 / 1024);
#endif
logvec[logvecpos].iov_base = mempkt;
@@ -107,35 +196,16 @@ void log_request(struct wsgi_request *wsgi_req) {
}
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n",
(int) uwsgi.mypid,
wsgi_req->app_id,
app_req,
(unsigned long long ) uwsgi.workers[0].requests,
wsgi_req->remote_addr_len, wsgi_req->remote_addr,
wsgi_req->remote_user_len, wsgi_req->remote_user,
wsgi_req->var_cnt,
wsgi_req->uh.pktsize,
24, time_request,
wsgi_req->method_len, wsgi_req->method,
wsgi_req->uri_len, wsgi_req->uri,
(unsigned long long) wsgi_req->response_size,
rt, tsize,
via,
wsgi_req->protocol_len, wsgi_req->protocol,
wsgi_req->status,
wsgi_req->header_cnt,
(unsigned long long) wsgi_req->headers_size,
wsgi_req->switches, wsgi_req->async_id);
rlen = snprintf(logpkt, 4096, "[pid: %d|app: %d|req: %d/%llu] %.*s (%.*s) {%d vars in %d bytes} [%.*s] %.*s %.*s => generated %llu bytes in %ld %s%s(%.*s %d) %d headers in %llu bytes (%d switches on core %d)\n", (int) uwsgi.mypid, wsgi_req->app_id, app_req, (unsigned long long) uwsgi.workers[0].requests, wsgi_req->remote_addr_len, wsgi_req->remote_addr, wsgi_req->remote_user_len, wsgi_req->remote_user, wsgi_req->var_cnt, wsgi_req->uh.pktsize, 24, time_request, wsgi_req->method_len, wsgi_req->method, wsgi_req->uri_len, wsgi_req->uri, (unsigned long long) wsgi_req->response_size, rt, tsize, via, wsgi_req->protocol_len, wsgi_req->protocol, wsgi_req->status, wsgi_req->header_cnt, (unsigned long long) wsgi_req->headers_size, wsgi_req->switches, wsgi_req->async_id);
logvec[logvecpos].iov_base = logpkt;
logvec[logvecpos].iov_len = rlen;
// do not check for errors
rlen = writev(2, logvec, logvecpos+1);
rlen = writev(2, logvec, logvecpos + 1);
}
void get_memusage(uint64_t *rss, uint64_t *vsz) {
void get_memusage(uint64_t * rss, uint64_t * vsz) {
#ifdef UNBIT
*vsz = syscall(356);
@@ -146,7 +216,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
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 %*s %llu %lld", (unsigned long long *) vsz, (unsigned long long *) rss);
if (i != 2) {
uwsgi_log( "warning: invalid record in /proc/self/stat\n");
uwsgi_log("warning: invalid record in /proc/self/stat\n");
}
fclose(procfile);
}
@@ -157,7 +227,7 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
procfd = open("/proc/self/psinfo", O_RDONLY);
if (procfd >= 0) {
if ( read(procfd, (char *) &info, sizeof(info)) > 0) {
if (read(procfd, (char *) &info, sizeof(info)) > 0) {
*rss = (uint64_t) info.pr_rssize * 1024;
*vsz = (uint64_t) info.pr_size * 1024;
}
@@ -215,12 +285,56 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
*vsz = 0;
*rss = 0;
while(get_next_area_info(0, &cookie, &ai) == B_OK) {
while (get_next_area_info(0, &cookie, &ai) == B_OK) {
*vsz += ai.ram_size;
if ( (ai.protection & B_WRITE_AREA) != 0) {
if ((ai.protection & B_WRITE_AREA) != 0) {
*rss += ai.ram_size;
}
}
#endif
}
void uwsgi_register_logger(char *name, ssize_t(*func) (struct uwsgi_logger *, char *, size_t)) {
struct uwsgi_logger *ul = uwsgi.loggers, *old_ul;
if (!ul) {
uwsgi.loggers = uwsgi_malloc(sizeof(struct uwsgi_logger));
ul = uwsgi.loggers;
}
else {
while (ul) {
old_ul = ul;
ul = ul->next;
}
ul = uwsgi_malloc(sizeof(struct uwsgi_logger));
old_ul->next = ul;
}
ul->name = name;
ul->func = func;
ul->next = NULL;
ul->configured = 0;
ul->fd = -1;
ul->data = NULL;
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-logger] registered \"%s\"\n", ul->name);
#endif
}
struct uwsgi_logger *uwsgi_get_logger(char *name) {
struct uwsgi_logger *ul = uwsgi.loggers;
while (ul) {
if (!strcmp(ul->name, name)) {
return ul;
}
ul = ul->next;
}
return NULL;
}
+47
View File
@@ -0,0 +1,47 @@
[uwsgi]
for = 4031 14032 4033 14034 24035
socket = /tmp/%(_)/uwsgi.sock
socket = 192.*:%(_)
print = ciao %(_) hello %(_) bye %(_)
endfor =
socket = :4045
socket = :4046
socket = :4047
socket = :4048
socket = :4049
socket = :4050
socket = :4051
show-config =
if-env = PIPPO
print =
print = PIPPO e' definita e il suo valore e' %(_) boh
endif =
socket = :5051
socket = :5052
socket = :5053
socket = :5054
if-exists = /etc/services
print = il file %(_) esiste $(PATH)
endif =
if-exists = /etc/foobar
print = il file %(_) esiste $(PATH)
endif =
socket = :6060
if-file = /etc/fstab
socket = :7171
endif =
ifdir = /tmp
print = %(_) is a directory
endif=
+7 -1
View File
@@ -40,9 +40,9 @@ void *simple_loop(void *arg1) {
long core_id = (long) arg1;
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
int i;
#ifdef UWSGI_THREADING
int i;
//PyThreadState *pts;
sigset_t smask;
@@ -55,6 +55,9 @@ void *simple_loop(void *arg1) {
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
#ifdef UWSGI_DEBUG
sigdelset(&smask, SIGSEGV);
#endif
pthread_sigmask(SIG_BLOCK, &smask, NULL);
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init_thread) {
@@ -128,6 +131,9 @@ void *zeromq_loop(void *arg1) {
if (core_id > 0) {
// block all signals on new threads
sigfillset(&smask);
#ifdef UWSGI_DEBUG
sigdelset(&smask, SIGSEGV);
#endif
pthread_sigmask(SIG_BLOCK, &smask, NULL);
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init_thread) {
+763 -854
View File
File diff suppressed because it is too large Load Diff
+546 -131
View File
@@ -2,7 +2,320 @@
extern struct uwsgi_server uwsgi;
void worker_wakeup() {}
void worker_wakeup() {
}
int uwsgi_calc_cheaper(void) {
int i;
int needed_workers = uwsgi.cheaper_algo();
if (needed_workers > 0) {
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
if (uwsgi_respawn_worker(i))
return 0;
needed_workers--;
}
if (needed_workers == 0)
break;
}
}
else if (needed_workers < 0) {
int oldest_worker = 0;
time_t oldest_worker_spawn = INT_MAX;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
if (uwsgi.workers[i].last_spawn < oldest_worker_spawn) {
oldest_worker_spawn = uwsgi.workers[i].last_spawn;
oldest_worker = i;
}
}
}
if (oldest_worker > 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("worker %d should die...\n", oldest_worker);
#endif
uwsgi.workers[oldest_worker].cheaped = 1;
uwsgi.workers[oldest_worker].manage_next_request = 0;
// wakeup task in case of wait
(void) kill(uwsgi.workers[oldest_worker].pid, SIGWINCH);
}
}
return 1;
}
/*
-- Cheaper, spare algorithm, adapted from old-fashioned spare system --
when all of the workers are busy, the overload_count is incremented.
as soon as overload_count is higher than uwsgi.cheaper_overload (--cheaper-overload options)
at most cheaper_step (default to 1) new workers are spawned.
when at least one worker is free, the overload_count is decremented and the idle_count is incremented.
If overload_count reaches 0, the system will count active workers (the ones uncheaped) and busy workers (the ones running a request)
if there is exacly 1 free worker we are in "stable state" (1 spare worker available). no worker will be touched.
if the number of active workers is higher than uwsgi.cheaper_count and at least uwsgi.cheaper_overload cycles are passed from the last
"cheap it" procedure, then cheap a worker.
Example:
10 processes
2 cheaper
2 cheaper step
3 cheaper_overload
1 second master cycle
there are 7 workers running (triggered by some kind of spike activity).
Of this, 6 are busy, 1 is free. We are in stable state.
After a bit the spike disappear and idle_count start to increase.
After 3 seconds (uwsgi.cheaper_overload cycles) the oldest worker will be cheaped. This will happens
every seconds (uwsgi.cheaper_overload cycles) til the number of workers is == uwsgi.cheaper_count.
If during the "cheap them all" procedure, an overload condition come again (another spike) the "cheap them all"
will be interrupted.
*/
int uwsgi_cheaper_algo_spare(void) {
int i;
static uint64_t overload_count = 0;
static uint64_t idle_count = 0;
// step 1 -> count the number of busy workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
// if a non-busy worker is found, the overload_count is decremented and stop the cycle
if (uwsgi.workers[i].busy == 0) {
if (overload_count > 0)
overload_count--;
goto healthy;
}
}
}
overload_count++;
idle_count = 0;
healthy:
// are we overloaded ?
if (overload_count > uwsgi.cheaper_overload) {
#ifdef UWSGI_DEBUG
uwsgi_log("overloaded !!!\n");
#endif
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step)
break;
}
}
// reset overload
overload_count = 0;
// return the maximum number of workers to spawn
return decheaped;
}
// we are no more overloaded
else if (overload_count == 0) {
// how many active workers ?
int active_workers = 0;
int busy_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
active_workers++;
if (uwsgi.workers[i].busy == 1)
busy_workers++;
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("active workers %d busy_workers %d\n", active_workers, busy_workers);
#endif
// special condition: uwsgi.cheaper running workers and 1 free
if (active_workers > busy_workers && active_workers - busy_workers == 1) {
#ifdef UWSGI_DEBUG
uwsgi_log("stable status: 1 spare worker\n");
#endif
return 0;
}
idle_count++;
if (active_workers > uwsgi.cheaper_count && idle_count % uwsgi.cheaper_overload == 0) {
// we are in "cheap them all"
return -1;
}
}
return 0;
}
/*
-- Cheaper, backlog algorithm (supported only on Linux) --
increse the number of workers when the listen queue is higher than uwsgi.cheaper_overload.
Decrese when lower.
*/
int uwsgi_cheaper_algo_backlog(void) {
int i;
#ifdef __linux__
int backlog = uwsgi.shared->ti.tcpi_unacked;
#else
int backlog = 0;
#endif
if (backlog > (int)uwsgi.cheaper_overload) {
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step)
break;
}
}
// return the maximum number of workers to spawn
return decheaped;
}
else if (backlog < (int) uwsgi.cheaper_overload) {
int active_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
active_workers++;
}
}
if (active_workers > uwsgi.cheaper_count) {
return -1;
}
}
return 0;
}
// reload uWSGI, close unneded file descriptor, restore the original environment and re-exec the binary
void uwsgi_reload(char **argv) {
int i;
int waitpid_status;
// call a series of waitpid to ensure all processes (gateways, mules and daemons) are dead
for (i = 0; i < (ushared->gateways_cnt + uwsgi.daemons_cnt + uwsgi.mules_cnt); i++) {
waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
if (uwsgi.exit_on_reload) {
uwsgi_log("uWSGI: GAME OVER (insert coin)\n");
exit(0);
}
uwsgi_log("binary reloading uWSGI...\n");
uwsgi_log("chdir() to %s\n", uwsgi.cwd);
if (chdir(uwsgi.cwd)) {
uwsgi_error("chdir()");
}
/* check fd table (a module can obviosly open some fd on initialization...) */
uwsgi_log("closing all non-uwsgi socket fds > 2 (max_fd = %d)...\n", (int)uwsgi.max_fd);
for (i = 3; i < (int)uwsgi.max_fd; i++) {
int found = 0;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while (uwsgi_sock) {
if (i == uwsgi_sock->fd) {
uwsgi_log("found fd %d mapped to socket %d (%s)\n", i, uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
found = 1;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
if (!found) {
if (uwsgi.has_emperor) {
if (i == uwsgi.emperor_fd) {
found = 1;
}
}
}
if (uwsgi.log_master) {
if (uwsgi.original_log_fd > -1) {
if (i == uwsgi.original_log_fd) {
found = 1;
}
}
if (uwsgi.shared->worker_log_pipe[0] > -1) {
if (i == uwsgi.shared->worker_log_pipe[0]) {
found = 1;
}
}
if (uwsgi.shared->worker_log_pipe[1] > -1) {
if (i == uwsgi.shared->worker_log_pipe[1]) {
found = 1;
}
}
}
if (!found) {
#ifdef __APPLE__
fcntl(i, F_SETFD, FD_CLOEXEC);
#else
close(i);
#endif
}
}
#ifdef UWSGI_AS_SHARED_LIBRARY
return;
#else
uwsgi_log("running %s\n", uwsgi.binary_path);
uwsgi_flush_logs();
argv[0] = uwsgi.binary_path;
//strcpy (argv[0], uwsgi.binary_path);
if (uwsgi.log_master) {
if (uwsgi.original_log_fd > -1) {
dup2(uwsgi.original_log_fd, 1);
dup2(1, 2);
}
if (uwsgi.shared->worker_log_pipe[0] > -1) {
close(uwsgi.shared->worker_log_pipe[0]);
}
if (uwsgi.shared->worker_log_pipe[1] > -1) {
close(uwsgi.shared->worker_log_pipe[1]);
}
}
execvp(uwsgi.binary_path, argv);
uwsgi_error("execvp()");
// never here
exit(1);
#endif
}
void master_check_cluster_nodes() {
@@ -33,7 +346,7 @@ void master_check_cluster_nodes() {
}
}
void uwsgi_fixup_fds(int wid, int muleid) {
void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
int i;
@@ -43,48 +356,82 @@ void uwsgi_fixup_fds(int wid, int muleid) {
}
if (uwsgi.master_process) {
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].signal_pipe[0] != -1) close(uwsgi.workers[i].signal_pipe[0]);
if (i != wid) {
if (uwsgi.workers[i].signal_pipe[1] != -1) close(uwsgi.workers[i].signal_pipe[1]);
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.shared->spooler_pid != getpid()) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1) close (uwsgi.shared->spooler_signal_pipe[0]);
if (uwsgi.shared->spooler_signal_pipe[1] != -1) close (uwsgi.shared->spooler_signal_pipe[1]);
if (uwsgi.master_queue > -1)
close(uwsgi.master_queue);
// close gateways
if (!ug) {
for (i = 0; i < ushared->gateways_cnt; i++) {
close(ushared->gateways[i].internal_subscription_pipe[0]);
close(ushared->gateways[i].internal_subscription_pipe[1]);
}
}
struct uwsgi_gateway_socket *ugs = uwsgi.gateway_sockets;
while (ugs) {
if (ug && !strcmp(ug->name, ugs->owner)) {
ugs = ugs->next;
continue;
}
// do not close shared sockets !!!
if (!ugs->shared) {
close(ugs->fd);
}
ugs = ugs->next;
}
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].signal_pipe[0] != -1)
close(uwsgi.workers[i].signal_pipe[0]);
if (i != wid) {
if (uwsgi.workers[i].signal_pipe[1] != -1)
close(uwsgi.workers[i].signal_pipe[1]);
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.i_am_a_spooler && uwsgi.i_am_a_spooler->pid != getpid()) {
if (uwsgi.shared->spooler_signal_pipe[0] != -1)
close(uwsgi.shared->spooler_signal_pipe[0]);
if (uwsgi.shared->spooler_signal_pipe[1] != -1)
close(uwsgi.shared->spooler_signal_pipe[1]);
}
#endif
if (uwsgi.shared->mule_signal_pipe[0] != -1) close(uwsgi.shared->mule_signal_pipe[0]);
if (uwsgi.shared->mule_signal_pipe[0] != -1)
close(uwsgi.shared->mule_signal_pipe[0]);
if (muleid == 0) {
if (uwsgi.shared->mule_signal_pipe[1] != -1)
close(uwsgi.shared->mule_signal_pipe[1]);
if (uwsgi.shared->mule_queue_pipe[1] != -1)
close(uwsgi.shared->mule_queue_pipe[1]);
}
for (i = 0; i < uwsgi.mules_cnt; i++) {
if (uwsgi.mules[i].signal_pipe[0] != -1)
close(uwsgi.mules[i].signal_pipe[0]);
if (muleid != i + 1) {
if (uwsgi.mules[i].signal_pipe[1] != -1)
close(uwsgi.mules[i].signal_pipe[1]);
if (uwsgi.mules[i].queue_pipe[1] != -1)
close(uwsgi.mules[i].queue_pipe[1]);
}
}
for (i = 0; i < uwsgi.farms_cnt; i++) {
if (uwsgi.farms[i].signal_pipe[0] != -1)
close(uwsgi.farms[i].signal_pipe[0]);
if (muleid == 0) {
if (uwsgi.shared->mule_signal_pipe[1] != -1) close(uwsgi.shared->mule_signal_pipe[1]);
if (uwsgi.shared->mule_queue_pipe[1] != -1) close(uwsgi.shared->mule_queue_pipe[1]);
if (uwsgi.farms[i].signal_pipe[1] != -1)
close(uwsgi.farms[i].signal_pipe[1]);
if (uwsgi.farms[i].queue_pipe[1] != -1)
close(uwsgi.farms[i].queue_pipe[1]);
}
}
for(i=0;i<uwsgi.mules_cnt;i++) {
if (uwsgi.mules[i].signal_pipe[0] != -1) close(uwsgi.mules[i].signal_pipe[0]);
if (muleid != i+1) {
if (uwsgi.mules[i].signal_pipe[1] != -1) close(uwsgi.mules[i].signal_pipe[1]);
if (uwsgi.mules[i].queue_pipe[1] != -1) close(uwsgi.mules[i].queue_pipe[1]);
}
}
}
for(i=0;i<uwsgi.farms_cnt;i++) {
if (uwsgi.farms[i].signal_pipe[0] != -1) close(uwsgi.farms[i].signal_pipe[0]);
if (muleid == 0) {
if (uwsgi.farms[i].signal_pipe[1] != -1) close(uwsgi.farms[i].signal_pipe[1]);
if (uwsgi.farms[i].queue_pipe[1] != -1) close(uwsgi.farms[i].queue_pipe[1]);
}
}
}
}
int uwsgi_respawn_worker(int wid) {
@@ -92,6 +439,10 @@ int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
int i;
if (uwsgi.threaded_logger) {
pthread_mutex_lock(&uwsgi.threaded_logger_lock);
}
pid_t pid = uwsgi_fork(uwsgi.workers[wid].name);
if (pid == 0) {
@@ -102,8 +453,13 @@ int uwsgi_respawn_worker(int wid) {
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].rss_size = 0;
uwsgi.workers[uwsgi.mywid].vsz_size = 0;
// do not reset worker counters on reload !!!
//uwsgi.workers[uwsgi.mywid].requests = 0;
// ...but maintain a delta counter (yes this is racy in multithread)
uwsgi.workers[uwsgi.mywid].delta_requests = 0;
//uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
@@ -116,18 +472,18 @@ int uwsgi_respawn_worker(int wid) {
// reset the apps count with a copy from the master
uwsgi.workers[uwsgi.mywid].apps_cnt = uwsgi.workers[0].apps_cnt;
uwsgi_fixup_fds(wid, 0);
uwsgi_fixup_fds(wid, 0, NULL);
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
uwsgi.my_signal_socket = uwsgi.workers[wid].signal_pipe[1];
if (uwsgi.master_process) {
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
}
if ((uwsgi.workers[uwsgi.mywid].respawn_count || uwsgi.cheap)) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->master_fixup) {
uwsgi.p[i]->master_fixup(1);
}
}
}
}
return 1;
@@ -144,6 +500,11 @@ int uwsgi_respawn_worker(int wid) {
}
}
if (uwsgi.threaded_logger) {
pthread_mutex_unlock(&uwsgi.threaded_logger_lock);
}
return 0;
}
@@ -153,8 +514,7 @@ void uwsgi_manage_signal_cron(time_t now) {
struct tm *uwsgi_cron_delta;
int i;
uwsgi.current_time = now;
uwsgi_cron_delta = localtime(&uwsgi.current_time);
uwsgi_cron_delta = localtime(&now);
if (uwsgi_cron_delta) {
@@ -179,36 +539,30 @@ void uwsgi_manage_signal_cron(time_t now) {
uc_hour = uwsgi_cron_delta->tm_hour;
if (ucron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
int run_task = 0;
// mday and wday are ORed
if (ucron->day == -1 && ucron->week == -1) {
if (ucron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (ucron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->day == -1) {
ucron->day = uwsgi_cron_delta->tm_mday;
}
else if (ucron->week == -1) {
ucron->week = uwsgi_cron_delta->tm_wday;
if (ucron->day != -1 && ucron->week != -1) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (ucron->day == uwsgi_cron_delta->tm_mday) {
ucron->week = uwsgi_cron_delta->tm_wday;
}
else if (ucron->week == uwsgi_cron_delta->tm_wday) {
ucron->day = uwsgi_cron_delta->tm_mday;
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
if (run_task == 1) {
// date match, signal it ?
if (uwsgi.current_time - ucron->last_job > 60) {
if (now - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = uwsgi.current_time;
ucron->last_job = now;
}
}
@@ -228,8 +582,7 @@ void uwsgi_manage_command_cron(time_t now) {
struct uwsgi_cron *current_cron = uwsgi.crons;
int uc_minute, uc_hour, uc_day, uc_month, uc_week;
uwsgi.current_time = now;
uwsgi_cron_delta = localtime(&uwsgi.current_time);
uwsgi_cron_delta = localtime(&now);
if (!uwsgi_cron_delta) {
@@ -252,41 +605,36 @@ void uwsgi_manage_command_cron(time_t now) {
uc_hour = uwsgi_cron_delta->tm_hour;
if (current_cron->month == -1)
uc_month = uwsgi_cron_delta->tm_mon;
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
int run_task = 0;
// mday and wday are ORed
if (current_cron->day == -1 && current_cron->week == -1) {
if (current_cron->day == -1)
uc_day = uwsgi_cron_delta->tm_mday;
if (current_cron->week == -1)
uc_week = uwsgi_cron_delta->tm_wday;
}
else if (current_cron->day == -1) {
current_cron->day = uwsgi_cron_delta->tm_mday;
}
else if (current_cron->week == -1) {
current_cron->week = uwsgi_cron_delta->tm_wday;
if (current_cron->day != -1 && current_cron->week != -1) {
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && (uwsgi_cron_delta->tm_mday == uc_day || uwsgi_cron_delta->tm_wday == uc_week)) {
run_task = 1;
}
}
else {
if (current_cron->day == uwsgi_cron_delta->tm_mday) {
current_cron->week = uwsgi_cron_delta->tm_wday;
}
else if (current_cron->week == uwsgi_cron_delta->tm_wday) {
current_cron->day = uwsgi_cron_delta->tm_mday;
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
run_task = 1;
}
}
if (uwsgi_cron_delta->tm_min == uc_minute && uwsgi_cron_delta->tm_hour == uc_hour && uwsgi_cron_delta->tm_mon == uc_month && uwsgi_cron_delta->tm_mday == uc_day && uwsgi_cron_delta->tm_wday == uc_week) {
if (run_task == 1) {
// date match, run command ?
if (uwsgi.current_time - current_cron->last_job > 60) {
if (now - current_cron->last_job > 60) {
//call command
if (current_cron->command) {
if (uwsgi_run_command(current_cron->command) >=0) {
if (uwsgi_run_command(current_cron->command, NULL, -1) >= 0) {
uwsgi_log_verbose("[uWSGI-cron] running %s\n", current_cron->command);
}
}
current_cron->last_job = uwsgi.current_time;
current_cron->last_job = now;
}
}
@@ -303,7 +651,7 @@ void uwsgi_manage_command_cron(time_t now) {
void uwsgi_send_stats(int fd) {
int i,j;
int i, j;
struct sockaddr_un client_src;
struct uwsgi_app *ua;
socklen_t client_src_len = 0;
@@ -326,63 +674,100 @@ void uwsgi_send_stats(int fd) {
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
#endif
fprintf(output,"\"uid\": %d,\n", (int)(getuid()));
fprintf(output,"\"gid\": %d,\n", (int)(getgid()));
stats_send_llu("\"load\": %llu,\n", uwsgi.shared->load);
fprintf(output, "\"pid\": %d,\n", (int) (getpid()));
fprintf(output, "\"uid\": %d,\n", (int) (getuid()));
fprintf(output, "\"gid\": %d,\n", (int) (getgid()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
if (uwsgi.daemons) {
fprintf(output, "\"daemons\": [\n");
struct uwsgi_daemon *ud = uwsgi.daemons;
while (ud) {
fprintf(output, "\t{ \"cmd\": \"%s\", \"pid\": %d, \"respawns\": %llu }", ud->command, (int) ud->pid, (unsigned long long) ud->respawns - 1);
if (ud->next)
fprintf(output, ",\n");
else {
fprintf(output, "\n");
}
ud = ud->next;
}
fprintf(output, "],\n");
}
fprintf(output, "\"locks\": [\n");
struct uwsgi_lock_item *uli = uwsgi.registered_locks;
while (uli) {
if (uli->next) {
fprintf(output, "\t{ \"%s\": %d },\n", uli->id, (int) uli->pid);
}
else {
fprintf(output, "\t{ \"%s\": %d }\n", uli->id, (int) uli->pid);
}
uli = uli->next;
}
fprintf(output, "],\n");
fprintf(output, "\"workers\": [\n");
for (i = 0; i < uwsgi.numproc; i++) {
fprintf(output,"\t{");
fprintf(output, "\t{");
fprintf(output,"\"id\": %d, ", uwsgi.workers[i+1].id);
fprintf(output,"\"pid\": %d, ", (int) uwsgi.workers[i+1].pid);
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i+1].requests);
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i+1].exceptions);
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i+1].signals);
fprintf(output, "\"id\": %d, ", uwsgi.workers[i + 1].id);
fprintf(output, "\"pid\": %d, ", (int) uwsgi.workers[i + 1].pid);
stats_send_llu("\"requests\": %llu, ", uwsgi.workers[i + 1].requests);
stats_send_llu("\"delta_requests\": %llu, ", uwsgi.workers[i + 1].delta_requests);
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i + 1].exceptions);
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i + 1].signals);
if (uwsgi.workers[i + 1].cheaped) {
fprintf(output,"\"status\": \"cheap\", ");
fprintf(output, "\"status\": \"cheap\", ");
}
else if (uwsgi.workers[i + 1].suspended && !uwsgi.workers[i + 1].busy) {
fprintf(output, "\"status\": \"pause\", ");
}
else if (uwsgi.workers[i + 1].suspended) {
fprintf(output,"\"status\": \"pause\", ");
}
else {
if (uwsgi.workers[i + 1].sig) {
fprintf(output,"\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
fprintf(output, "\"status\": \"sig%d\", ", uwsgi.workers[i + 1].signum);
}
else if (uwsgi.workers[i + 1].busy) {
fprintf(output,"\"status\": \"busy\", ");
}
else {
fprintf(output,"\"status\": \"idle\", ");
}
}
else if (uwsgi.workers[i + 1].busy) {
fprintf(output, "\"status\": \"busy\", ");
}
else {
fprintf(output, "\"status\": \"idle\", ");
}
}
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i+1].rss_size);
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i+1].vsz_size);
stats_send_llu("\"rss\": %llu, ", uwsgi.workers[i + 1].rss_size);
stats_send_llu("\"vsz\": %llu, ", uwsgi.workers[i + 1].vsz_size);
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i+1].running_time);
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i+1].last_spawn);
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i+1].respawn_count);
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i+1].tx);
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i+1].avg_response_time);
stats_send_llu("\"running_time\": %llu, ", uwsgi.workers[i + 1].running_time);
stats_send_llu("\"last_spawn\": %llu, ", uwsgi.workers[i + 1].last_spawn);
stats_send_llu("\"respawn_count\": %llu, ", uwsgi.workers[i + 1].respawn_count);
stats_send_llu("\"tx\": %llu, ", uwsgi.workers[i + 1].tx);
stats_send_llu("\"avg_rt\": %llu, ", uwsgi.workers[i + 1].avg_response_time);
fprintf(output,"\"apps\": [\n");
fprintf(output, "\"apps\": [\n");
for(j=0;j<uwsgi.workers[i+1].apps_cnt;j++) {
ua = &uwsgi.workers[i+1].apps[j];
fprintf(output,"\t\t{ ");
for (j = 0; j < uwsgi.workers[i + 1].apps_cnt; j++) {
ua = &uwsgi.workers[i + 1].apps[j];
fprintf(output, "\t\t{ ");
fprintf(output, "\"id\": %d, ", j);
fprintf(output, "\"modifier1\": %d, ", ua->modifier1);
fprintf(output, "\"mountpoint\": \"%.*s\", ", ua->mountpoint_len, ua->mountpoint);
stats_send_llu( "\"requests\": %llu, ", ua->requests);
stats_send_llu( "\"exceptions\": %llu, ", ua->exceptions);
stats_send_llu("\"startup_time\": %llu, ", ua->startup_time);
stats_send_llu("\"requests\": %llu, ", ua->requests);
stats_send_llu("\"exceptions\": %llu, ", ua->exceptions);
if (ua->chdir) {
fprintf(output, "\"chdir\": \"%s\", ", ua->chdir);
@@ -390,25 +775,55 @@ void uwsgi_send_stats(int fd) {
else {
fprintf(output, "\"chdir\": \"\" ");
}
if (j == uwsgi.workers[i+1].apps_cnt-1) {
fprintf(output,"}\n");
if (j == uwsgi.workers[i + 1].apps_cnt - 1) {
fprintf(output, "}\n");
}
else {
fprintf(output,"},\n");
fprintf(output, "},\n");
}
}
fprintf(output,"\t\t]");
fprintf(output, "\t\t]");
if (i == uwsgi.numproc-1) {
fprintf(output,"}\n");
if (i == uwsgi.numproc - 1) {
fprintf(output, "}\n");
}
else {
fprintf(output,"},\n");
fprintf(output, "},\n");
}
}
fprintf(output,"]}\n");
fprintf(output, "]}\n");
fclose(output);
}
void uwsgi_register_cheaper_algo(char *name, int(*func) (void)) {
struct uwsgi_cheaper_algo *uca = uwsgi.cheaper_algos;
if (!uca) {
uwsgi.cheaper_algos = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
uca = uwsgi.cheaper_algos;
}
else {
while (uca) {
if (!uca->next) {
uca->next = uwsgi_malloc(sizeof(struct uwsgi_cheaper_algo));
uca = uca->next;
break;
}
uca = uca->next;
}
}
uca->name = name;
uca->func = func;
uca->next = NULL;
#ifdef UWSGI_DEBUG
uwsgi_log("[uwsgi-cheaper-algo] registered \"%s\"\n", uca->name);
#endif
}
+4
View File
@@ -19,4 +19,8 @@
<module>trac.web.main:dispatch_request</module>
</uwsgi>
<uwsgi>
<socket>:3031</socket>
</uwsgi>
</unbit>
+22 -1
View File
@@ -41,7 +41,7 @@ void uwsgi_mule(int id) {
uwsgi.mules[id-1].id = id;
uwsgi.mules[id-1].pid = getpid();
uwsgi_fixup_fds(0, id);
uwsgi_fixup_fds(0, id, NULL);
uwsgi.my_signal_socket = uwsgi.mules[id-1].signal_pipe[1];
uwsgi.signal_socket = uwsgi.shared->mule_signal_pipe[1];
@@ -356,3 +356,24 @@ clear:
return len;
}
void uwsgi_opt_add_mule(char *opt, char *value, void *foobar) {
uwsgi.mules_cnt++;
uwsgi_string_new_list(&uwsgi.mules_patches, value);
}
void uwsgi_opt_add_mules(char *opt, char *value, void *foobar) {
int i;
for(i=0;i<atoi(value);i++) {
uwsgi.mules_cnt++;
uwsgi_string_new_list(&uwsgi.mules_patches, NULL);
}
}
void uwsgi_opt_add_farm(char *opt, char *value, void *foobar) {
uwsgi.farms_cnt++;
uwsgi_string_new_list(&uwsgi.farms_list, value);
}
+18 -2
View File
@@ -1,5 +1,14 @@
<uwsgi>
<!--
DO NOT USE <app> TAG !!!
It is deprecated and will be removed from 1.2
-->
<plugins>psgi</plugins>
<plugins>rack</plugins>
<http>:9090</http>
@@ -24,6 +33,8 @@
<module>werkzeug.testapp:test_app</module>
</app>
<app mountpoint="/foobar">werkzeug.testapp:test_app</app>
<app mountpoint="/trac">
<module>trac.web.main:dispatch_request</module>
</app>
@@ -32,11 +43,12 @@
<module>werkzeug.testapp:test_app</module>
</app>
<!-- eval is broken -->
<app mountpoint="/bzr">
<eval>
<eval>
from bzrlib.transport.http import wsgi
application = wsgi.make_app("mybzr", "/bzr", readonly=False)
</eval>
</eval>
</app>
<app domain="sirius002:9090">
@@ -47,4 +59,8 @@ application = wsgi.make_app("mybzr", "/bzr", readonly=False)
<rack>config2.ru</rack>
</app>
<app mountpoint="precise64.local">
<psgi>test.psgi</psgi>
</app>
</uwsgi>
+97 -44
View File
@@ -2,30 +2,16 @@
extern struct uwsgi_server uwsgi;
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option, int absolute) {
void *plugin_handle;
char *plugin_name;
char *plugin_entry_symbol;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
int linkpath_size;
static int plugin_already_loaded(const char *plugin) {
int i;
char *colon = strchr(plugin, ':');
if (colon) {
colon[0] = 0;
}
check:
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->name) {
if (!strcmp(plugin, uwsgi.p[i]->name)) {
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
return 1;
}
}
if (uwsgi.p[i]->alias) {
@@ -33,7 +19,7 @@ check:
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
return 1;
}
}
}
@@ -45,7 +31,7 @@ check:
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
return 1;
}
}
if (uwsgi.gp[i]->alias) {
@@ -53,37 +39,78 @@ check:
#ifdef UWSGI_DEBUG
uwsgi_log("%s plugin already available\n", plugin);
#endif
return NULL;
return 1;
}
}
}
return 0;
}
void *uwsgi_load_plugin(int modifier, char *plugin, char *has_option) {
void *plugin_handle = NULL;
int need_free = 0;
char *plugin_name = plugin;
char *plugin_symbol_name_start = plugin;
struct uwsgi_plugin *up;
char linkpath_buf[1024], linkpath[1024];
int linkpath_size;
char *colon = strchr(plugin_name, ':');
if (colon) {
plugin = colon+1;
colon[0] = 0;
modifier = atoi(plugin_name);
plugin_name = colon+1;
colon[0] = ':';
colon = NULL;
goto check;
}
if (absolute == 1) {
plugin_name = uwsgi_concat2(plugin, "");
// need to fix this... postpone until needed
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
}
else if (absolute == 2) {
plugin_name = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin);
plugin_entry_symbol = uwsgi_concat2n(plugin, strlen(plugin)-3 ,"", 0);
if (!uwsgi_endswith(plugin_name, "_plugin.so")) {
plugin_name = uwsgi_concat2(plugin_name, "_plugin.so");
need_free = 1;
}
else {
plugin_name = uwsgi_concat4(UWSGI_PLUGIN_DIR, "/", plugin, "_plugin.so");
plugin_entry_symbol = uwsgi_concat2(plugin, "_plugin");
plugin_symbol_name_start = plugin_name;
// step 1: check for absolute plugin (stop if it fails)
if (strchr(plugin_name, '/')) {
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
if (!plugin_handle) {
uwsgi_log( "%s\n", dlerror());
goto end;
}
plugin_symbol_name_start = uwsgi_get_last_char(plugin_name, '/');
plugin_symbol_name_start++;
}
// step dir, check for user-supplied plugins directory
struct uwsgi_string_list *pdir = uwsgi.plugins_dir;
while(pdir) {
char *plugin_filename = uwsgi_concat3(pdir->value, "/", plugin_name);
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
if (plugin_handle) {
free(plugin_filename);
break;
}
free(plugin_filename);
pdir = pdir->next;
}
// last step: search in compile-time plugin_dir
if (!plugin_handle) {
char *plugin_filename = uwsgi_concat3(UWSGI_PLUGIN_DIR, "/", plugin_name);
plugin_handle = dlopen(plugin_filename, RTLD_NOW | RTLD_GLOBAL);
free(plugin_filename);
}
plugin_handle = dlopen(plugin_name, RTLD_NOW | RTLD_GLOBAL);
if (!plugin_handle) {
uwsgi_log( "%s\n", dlerror());
}
else {
char *plugin_entry_symbol = uwsgi_concat2n(plugin_symbol_name_start, strlen(plugin_symbol_name_start)-3, "", 0);
up = dlsym(plugin_handle, plugin_entry_symbol);
if (!up) {
// is it a link ?
@@ -92,9 +119,11 @@ check:
if ((linkpath_size = readlink(plugin_name, linkpath_buf, 1023)) > 0) {
do {
linkpath_buf[linkpath_size] = '\0';
strcpy(linkpath, linkpath_buf);
strncpy(linkpath, linkpath_buf, linkpath_size+1);
} while ((linkpath_size = readlink(linkpath, linkpath_buf, 1023)) > 0);
#ifdef UWSGI_DEBUG
uwsgi_log("%s\n", linkpath);
#endif
free(plugin_entry_symbol);
up = dlsym(plugin_handle, plugin_entry_symbol);
char *slash = uwsgi_get_last_char(linkpath, '/');
@@ -109,23 +138,41 @@ check:
}
}
if (up) {
if (!up->name) {
uwsgi_log("the loaded plugin (%s) has no .name attribute\n", plugin_name);
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
free(plugin_entry_symbol);
return NULL;
}
if (plugin_already_loaded(up->name)) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
if (need_free)
free(plugin_name);
free(plugin_entry_symbol);
return NULL;
}
if (has_option) {
struct option *lopt = up->options, *aopt;
struct uwsgi_option *op = uwsgi.options;
int found = 0;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(has_option, aopt->name)) {
while (op && op->name) {
if (!strcmp(has_option, op->name)) {
found = 1;
break;
}
lopt++;
op++;
}
if (!found) {
if (dlclose(plugin_handle)) {
uwsgi_error("dlclose()");
}
free(plugin_name);
if (need_free)
free(plugin_name);
free(plugin_entry_symbol);
return NULL;
}
@@ -137,14 +184,20 @@ check:
else {
fill_plugin_table(up->modifier1, up);
}
free(plugin_name);
if (need_free)
free(plugin_name);
free(plugin_entry_symbol);
if (up->on_load)
up->on_load();
return plugin_handle;
}
uwsgi_log( "%s\n", dlerror());
}
free(plugin_name);
end:
if (need_free)
free(plugin_name);
return NULL;
}
+3 -2
View File
@@ -34,6 +34,7 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
uint64_t vallen = 0;
char *value;
char *argv[3];
uint16_t argvs[3];
uint8_t argc = 0;
switch(wsgi_req->uh.modifier2) {
@@ -52,9 +53,9 @@ int uwsgi_cache_request(struct wsgi_request *wsgi_req) {
// set
if (wsgi_req->uh.pktsize > 0) {
argc = 3;
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, &argc)) {
if (!uwsgi_parse_array(wsgi_req->buffer, wsgi_req->uh.pktsize, argv, argvs, &argc)) {
if (argc > 1) {
uwsgi_cache_set(argv[0], strlen(argv[0]), argv[1], strlen(argv[1]), 0, 0);
uwsgi_cache_set(argv[0], argvs[0], argv[1], argvs[1], 0, 0);
}
}
}
+62 -41
View File
@@ -2,12 +2,6 @@
extern struct uwsgi_server uwsgi;
#define CARBON_OPT_BASE 178000
#define CARBON_OPT_CARBON CARBON_OPT_BASE+1
#define CARBON_OPT_CARBON_ID CARBON_OPT_BASE+2
#define CARBON_OPT_CARBON_FREQ CARBON_OPT_BASE+3
#define CARBON_OPT_CARBON_TIMEOUT CARBON_OPT_BASE+4
struct uwsgi_carbon {
struct uwsgi_string_list *servers;
int freq;
@@ -15,41 +9,16 @@ struct uwsgi_carbon {
char *id;
} u_carbon;
struct option carbon_options[] = {
{"carbon", required_argument, 0, CARBON_OPT_CARBON},
{"carbon-timeout", required_argument, 0, CARBON_OPT_CARBON_TIMEOUT},
{"carbon-freq", required_argument, 0, CARBON_OPT_CARBON_FREQ},
{"carbon-id", required_argument, 0, CARBON_OPT_CARBON_ID},
{0, 0, 0, 0},
struct uwsgi_option carbon_options[] = {
{"carbon", required_argument, 0, "push statistics to the specified carbon server", uwsgi_opt_add_string_list, &u_carbon.servers, UWSGI_OPT_MASTER},
{"carbon-timeout", required_argument, 0, "set carbon connection timeout", uwsgi_opt_set_int, &u_carbon.timeout, 0},
{"carbon-freq", required_argument, 0, "set carbon push frequency", uwsgi_opt_set_int, &u_carbon.freq, 0},
{"carbon-id", required_argument, 0, "set carbon id", uwsgi_opt_set_str, &u_carbon.id, 0},
{0, 0, 0, 0, 0, 0, 0},
};
int carbon_init() {
return 0;
}
int carbon_opt(int i, char *optarg) {
switch(i) {
case CARBON_OPT_CARBON:
uwsgi.master_process = 1;
uwsgi_string_new_list(&u_carbon.servers, optarg);
return 1;
case CARBON_OPT_CARBON_ID:
u_carbon.id = optarg;
return 1;
case CARBON_OPT_CARBON_FREQ:
u_carbon.freq = atoi(optarg);
return 1;
case CARBON_OPT_CARBON_TIMEOUT:
u_carbon.timeout = atoi(optarg);
return 1;
}
return 0;
}
void carbon_post_init() {
int i;
@@ -94,6 +63,13 @@ void carbon_master_cycle() {
// put the socket in non-blocking mode
uwsgi_socket_nb(fd);
unsigned long long total_rss = 0;
unsigned long long total_vsz = 0;
unsigned long long total_tx = 0;
unsigned long long total_avg_rt = 0; // total avg_rt
unsigned long long avg_rt = 0; // per worker avg_rt reported to carbon
unsigned long long avg_rt_workers = 0; // number of workers used to calculate total avg_rt
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
@@ -102,22 +78,67 @@ void carbon_master_cycle() {
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
total_rss += uwsgi.workers[i].rss_size;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].rss_size, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
total_vsz += uwsgi.workers[i].vsz_size;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].vsz_size, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
if (uwsgi.workers[i].cheaped) {
// also if worker is cheaped than we report its average response time as zero, sending last value might be confusing
avg_rt = 0;
}
else {
// global average response time is calcucalted from active/idle workers, cheaped workers are excluded, otherwise it is not accurate
avg_rt = uwsgi.workers[i].avg_response_time;
avg_rt_workers++;
total_avg_rt += uwsgi.workers[i].avg_response_time;
}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) avg_rt, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
total_tx += uwsgi.workers[i].tx;
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].tx, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_rss, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.vsz_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_vsz, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.avg_rt %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) (avg_rt_workers ? total_avg_rt / avg_rt_workers : 0), (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.tx %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_tx, (unsigned long long ) uwsgi.current_time);
if (rlen < 1) goto clear;
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
clear:
close(fd);
nxt:
usl = usl->next;
}
last_update = time(NULL);
}
}
struct uwsgi_plugin carbon_plugin = {
.name = "carbon",
.options = carbon_options,
.manage_opt = carbon_opt,
.master_cycle = carbon_master_cycle,
.post_init = carbon_post_init,
.init = carbon_init,
};
+888 -45
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,70 @@
#include "../../uwsgi.h"
/*
This plugins is meant as an example for custom implementations.
-- Copy of Cheaper, backlog algorithm (supported only on Linux) --
increse the number of workers when the listen queue is higher than uwsgi.cheaper_overload.
Decrese when lower.
*/
extern struct uwsgi_server uwsgi;
int cheaper_backlog2_algo(void) {
int i;
#ifdef __linux__
int backlog = uwsgi.shared->ti.tcpi_unacked;
#else
int backlog = 0;
#endif
if (backlog > (int)uwsgi.cheaper_overload) {
// activate the first available worker (taking step into account)
int decheaped = 0;
// search for cheaped workers
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 1 && uwsgi.workers[i].pid == 0) {
decheaped++;
if (decheaped >= uwsgi.cheaper_step)
break;
}
}
// return the maximum number of workers to spawn
return decheaped;
}
else if (backlog < (int) uwsgi.cheaper_overload) {
// count active workers
int active_workers = 0;
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].pid > 0) {
active_workers++;
}
}
// cheap a worker if too much are running
if (active_workers > uwsgi.cheaper_count) {
return -1;
}
}
return 0;
}
// registration hook
void uwsgi_cheaper_register_backlog2(void) {
uwsgi_register_cheaper_algo("backlog2", cheaper_backlog2_algo);
}
struct uwsgi_plugin cheaper_backlog2_plugin = {
.name = "cheaper_backlog2",
.on_load = uwsgi_cheaper_register_backlog2,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='cheaper_backlog2'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['cheaper_backlog2']
+1 -1
View File
@@ -40,7 +40,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
fc = new FakeClass();
// get PATH_INFO
fc->foobar = uwsgi_get_var(wsgi_req, (char *) "PATH_INFO", &fc->foobar_len);
fc->foobar = uwsgi_get_var(wsgi_req, (char *) "PATH_INFO", 9, &fc->foobar_len);
if (fc->foobar) {
// send output
+16
View File
@@ -0,0 +1,16 @@
#include "../../uwsgi.h"
int dummy_request(struct wsgi_request *wsgi_req) {
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
return UWSGI_OK;
}
struct uwsgi_plugin dummy_plugin = {
.name = "dummy",
.modifier1 = 0,
.request = dummy_request,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='dummy'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['dummy']
+12 -26
View File
@@ -4,10 +4,10 @@
extern struct uwsgi_server uwsgi;
struct uwsgi_erlang uerl;
struct option erlang_options[] = {
{"erlang", required_argument, 0, LONG_ARGS_ERLANG},
{"erlang-cookie", required_argument, 0, LONG_ARGS_ERLANG_COOKIE},
{0, 0, 0, 0},
struct uwsgi_option erlang_options[] = {
{"erlang", required_argument, 0, "spawn an erlang c-node", uwsgi_opt_set_str, &uerl.name, UWSGI_OPT_MASTER},
{"erlang-cookie", required_argument, 0, "set erlang cookie", uwsgi_opt_set_str, &uerl.cookie, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -94,7 +94,8 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
char *call;
char buffer[0xffff];
char *argv[0xff] ;
char *argv[256] ;
uint16_t argvs[256] ;
int argc = 0;
uint16_t ret;
ei_x_buff xr;
@@ -215,14 +216,16 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
argc = 1;
argv[0] = uwsgi_malloc(esize+1);
ei_decode_atom(x->buff, &x->index, argv[0]);
argvs[1] = esize;
}
else if (etype == ERL_STRING_EXT) {
argc = 1;
argv[0] = uwsgi_malloc(esize+1);
ei_decode_string(x->buff, &x->index, argv[0]);
argvs[1] = esize;
}
ret = uwsgi_rpc(call, argc, argv, buffer);
ret = uwsgi_rpc(call, argc, argv, argvs, buffer);
#ifdef UWSGI_DEBUG
uwsgi_log("buffer: %.*s\n", ret, buffer);
@@ -241,7 +244,7 @@ void uwsgi_erlang_rpc(int fd, erlang_pid *from, ei_x_buff *x) {
}
void erlang_loop() {
void erlang_loop(int id) {
ErlConnect econn;
//ErlMessage em;
@@ -360,8 +363,7 @@ int erlang_init() {
char *nodename;
struct in_addr addr;
uerl.lock = uwsgi_mmap_shared_lock();
uwsgi_lock_init(uerl.lock);
uerl.lock = uwsgi_lock_init("erlang");
if (uerl.name) {
@@ -420,7 +422,7 @@ int erlang_init() {
uwsgi_log("Erlang C-Node %s registered on port %d\n", ei_thisnodename(&uerl.cnode), ntohs(sin.sin_port));
if (register_fat_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
if (register_gateway("uWSGI erlang c-node", erlang_loop) == NULL) {
uwsgi_log("unable to register the erlang gateway\n");
exit(1);
}
@@ -430,26 +432,10 @@ int erlang_init() {
return 0;
}
int erlang_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_ERLANG:
uwsgi.master_process = 1;
uerl.name = optarg;
return 1;
case LONG_ARGS_ERLANG_COOKIE:
uerl.cookie = optarg;
return 1;
}
return 0;
}
struct uwsgi_plugin erlang_plugin = {
.name = "erlang",
.options = erlang_options,
.manage_opt = erlang_opt,
.init = erlang_init,
};
-5
View File
@@ -1,10 +1,5 @@
#include <ei.h>
#define LONG_ARGS_ERLANG 17012
#define LONG_ARGS_ERLANG_COOKIE 17013
struct uwsgi_erlang_process {
char name[0xff];
+10 -2
View File
@@ -1,7 +1,15 @@
import os
NAME='erlang'
CFLAGS = []
LDFLAGS = []
ERLANGPATH = os.environ.get('UWSGICONFIG_ERLANGPATH', 'erl')
includedir = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, include)])\" -s erlang halt").read().rstrip()
libpath = os.popen(ERLANGPATH + " -noshell -noinput -eval \"io:format('~s~n', [code:lib_dir(erl_interface, lib)])\" -s erlang halt").read().rstrip()
CFLAGS = [ '-I' + includedir ]
LDFLAGS = [ '-L' + libpath ]
LIBS = ['-lei']
GCC_LIST = ['erlang']
File diff suppressed because it is too large Load Diff
+164
View File
@@ -0,0 +1,164 @@
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
#define FASTROUTER_STATUS_RECV_HDR 2
#define FASTROUTER_STATUS_RECV_VARS 3
#define FASTROUTER_STATUS_RESPONSE 4
#define FASTROUTER_STATUS_BUFFERING 5
#ifdef UWSGI_SCTP
#define FASTROUTER_STATUS_SCTP_NODE_FREE 6
#define FASTROUTER_STATUS_SCTP_RESPONSE 7
#endif
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
#define add_fake_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+1, x)
#define add_check_timeout(x) uwsgi_add_rb_timer(timeouts, time(NULL)+x, NULL)
#define del_check_timeout(x) rb_erase(&x->rbt, timeouts);
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
struct fastrouter_session;
struct uwsgi_fastrouter {
int (*mapper)(struct fastrouter_session *, char **);
int has_sockets;
int has_subscription_sockets;
#ifdef UWSGI_SCTP
int has_sctp_sockets;
#endif
int processes;
int quiet;
struct rb_root *timeouts;
int use_cache;
int nevents;
char *magic_table[0xff];
int queue;
char *pattern;
int pattern_len;
char *base;
int base_len;
size_t post_buffering;
char *pb_base_dir;
struct uwsgi_string_list *static_nodes;
struct uwsgi_string_list *current_static_node;
int static_node_gracetime;
char *stats_server;
int fr_stats_server;
int use_socket;
int socket_num;
struct uwsgi_socket *to_socket;
struct uwsgi_subscribe_slot *subscriptions;
int subscription_regexp;
struct uwsgi_string_list *fallback;
int socket_timeout;
uint8_t code_string_modifier1;
char *code_string_code;
char *code_string_function;
struct uwsgi_rb_timer *subscriptions_check;
int cheap;
int i_am_cheap;
int tolerance;
int harakiri;
struct fastrouter_session **fr_table;
};
#ifdef UWSGI_SCTP
struct uwsgi_fr_sctp_node {
int fd;
char name[64];
uint64_t requests;
struct uwsgi_fr_sctp_node *prev;
struct uwsgi_fr_sctp_node *next;
};
struct uwsgi_fr_sctp_node *uwsgi_fr_sctp_add_node(int);
void uwsgi_fr_sctp_del_node(int);
void uwsgi_opt_fastrouter_sctp(char *, char *, void *);
#endif
struct fastrouter_session {
int fd;
int instance_fd;
int status;
struct uwsgi_header uh;
uint8_t h_pos;
uint16_t pos;
char *hostname;
uint16_t hostname_len;
int has_key;
int retry;
#ifdef UWSGI_SCTP
int persistent;
#endif
char *instance_address;
uint64_t instance_address_len;
struct uwsgi_subscribe_node *un;
struct uwsgi_string_list *static_node;
int pass_fd;
int soopt;
int timed_out;
struct uwsgi_rb_timer *timeout;
int instance_failed;
size_t post_cl;
size_t post_remains;
struct uwsgi_string_list *fallback;
char *buf_file_name;
FILE *buf_file;
uint8_t modifier1;
uint8_t modifier2;
char *tmp_socket_name;
char buffer[0xffff];
};
void uwsgi_fastrouter_switch_events(struct fastrouter_session *, int intersting_fd, char **);
void close_session(struct fastrouter_session *);
void fr_get_hostname(char *, uint16_t, char *, uint16_t, void *);
int uwsgi_fr_map_use_void(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_cache(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_pattern(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_subscription(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_base(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_cs(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_to(struct fastrouter_session *, char **);
int uwsgi_fr_map_use_static_nodes(struct fastrouter_session *, char **);
#ifdef UWSGI_SCTP
int uwsgi_fr_map_use_sctp(struct fastrouter_session *, char **);
#endif
+428
View File
@@ -0,0 +1,428 @@
#include "../../uwsgi.h"
#include "fr.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_fastrouter ufr;
void uwsgi_fastrouter_switch_events(struct fastrouter_session *fr_session, int interesting_fd, char **magic_table) {
socklen_t solen = sizeof(int);
struct iovec iov[2];
struct msghdr msg;
union {
struct cmsghdr cmsg;
char control[CMSG_SPACE(sizeof(int))];
} msg_control;
struct cmsghdr *cmsg;
ssize_t len;
char *post_tmp_buf[0xffff];
switch (fr_session->status) {
case FASTROUTER_STATUS_RECV_HDR:
len = recv(fr_session->fd, (char *) (&fr_session->uh) + fr_session->h_pos, 4 - fr_session->h_pos, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(fr_session);
break;
}
fr_session->h_pos += len;
if (fr_session->h_pos == 4) {
#ifdef UWSGI_DEBUG
uwsgi_log("modifier1: %d pktsize: %d modifier2: %d\n", fr_session->uh.modifier1, fr_session->uh.pktsize, fr_session->uh.modifier2);
#endif
fr_session->status = FASTROUTER_STATUS_RECV_VARS;
}
break;
case FASTROUTER_STATUS_RECV_VARS:
if (interesting_fd == -1) {
goto choose_node;
}
len = recv(fr_session->fd, fr_session->buffer + fr_session->pos, fr_session->uh.pktsize - fr_session->pos, 0);
if (len <= 0) {
uwsgi_error("recv()");
close_session(fr_session);
break;
}
fr_session->pos += len;
if (fr_session->pos == fr_session->uh.pktsize) {
if (uwsgi_hooked_parse(fr_session->buffer, fr_session->uh.pktsize, fr_get_hostname, (void *) fr_session)) {
close_session(fr_session);
break;
}
if (fr_session->hostname_len == 0) {
close_session(fr_session);
break;
}
#ifdef UWSGI_DEBUG
//uwsgi_log("requested domain %.*s\n", fr_session->hostname_len, fr_session->hostname);
#endif
// the mapper hook
choose_node:
if (ufr.mapper(fr_session, magic_table))
break;
// no address found
if (!fr_session->instance_address_len) {
// if fallback nodes are configured, trigger them
if (ufr.fallback) {
fr_session->instance_failed = 1;
}
close_session(fr_session);
break;
}
if (ufr.post_buffering > 0 && fr_session->post_cl > ufr.post_buffering) {
fr_session->status = FASTROUTER_STATUS_BUFFERING;
fr_session->buf_file_name = uwsgi_tmpname(ufr.pb_base_dir, "uwsgiXXXXX");
if (!fr_session->buf_file_name) {
uwsgi_error("tempnam()");
close_session(fr_session);
break;
}
fr_session->post_remains = fr_session->post_cl;
// 2 + UWSGI_POSTFILE + 2 + fr_session->buf_file_name
if (fr_session->uh.pktsize + (2 + 14 + 2 + strlen(fr_session->buf_file_name)) > 0xffff) {
uwsgi_log("unable to buffer request body to file %s: not enough space\n", fr_session->buf_file_name);
close_session(fr_session);
break;
}
char *ptr = fr_session->buffer + fr_session->uh.pktsize;
uint16_t bfn_len = strlen(fr_session->buf_file_name);
*ptr++ = 14;
*ptr++ = 0;
memcpy(ptr, "UWSGI_POSTFILE", 14);
ptr += 14;
*ptr++ = (char) (bfn_len & 0xff);
*ptr++ = (char) ((bfn_len >> 8) & 0xff);
memcpy(ptr, fr_session->buf_file_name, bfn_len);
fr_session->uh.pktsize += 2 + 14 + 2 + bfn_len;
fr_session->buf_file = fopen(fr_session->buf_file_name, "w");
if (!fr_session->buf_file) {
uwsgi_error_open(fr_session->buf_file_name);
close_session(fr_session);
break;
}
}
else {
fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);
fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);
if (fr_session->instance_fd < 0) {
fr_session->instance_failed = 1;
fr_session->soopt = errno;
close_session(fr_session);
break;
}
fr_session->status = FASTROUTER_STATUS_CONNECTING;
ufr.fr_table[fr_session->instance_fd] = fr_session;
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
}
}
break;
case FASTROUTER_STATUS_CONNECTING:
if (interesting_fd == fr_session->instance_fd) {
if (getsockopt(fr_session->instance_fd, SOL_SOCKET, SO_ERROR, (void *) (&fr_session->soopt), &solen) < 0) {
uwsgi_error("getsockopt()");
fr_session->instance_failed = 1;
close_session(fr_session);
break;
}
if (fr_session->soopt) {
fr_session->instance_failed = 1;
close_session(fr_session);
break;
}
fr_session->uh.modifier1 = fr_session->modifier1;
iov[0].iov_base = &fr_session->uh;
iov[0].iov_len = 4;
iov[1].iov_base = fr_session->buffer;
iov[1].iov_len = fr_session->uh.pktsize;
// increment node requests counter
if (fr_session->un)
fr_session->un->requests++;
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (fr_session->pass_fd && !uwsgi.no_fd_passing) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
msg.msg_iovlen = 2;
msg.msg_flags = 0;
msg.msg_control = &msg_control;
msg.msg_controllen = sizeof(msg_control);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_len = CMSG_LEN(sizeof(int));
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
memcpy(CMSG_DATA(cmsg), &fr_session->fd, sizeof(int));
if (sendmsg(fr_session->instance_fd, &msg, 0) < 0) {
uwsgi_error("sendmsg()");
}
close_session(fr_session);
break;
}
if (writev(fr_session->instance_fd, iov, 2) < 0) {
uwsgi_error("writev()");
close_session(fr_session);
break;
}
event_queue_fd_write_to_read(ufr.queue, fr_session->instance_fd);
fr_session->status = FASTROUTER_STATUS_RESPONSE;
}
break;
#ifdef UWSGI_SCTP
case FASTROUTER_STATUS_SCTP_NODE_FREE:
{
struct sctp_sndrcvinfo sinfo;
int msg_flags = 0;
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
len = sctp_recvmsg(interesting_fd, fr_session->buffer, 0xffff, NULL, NULL, &sinfo, &msg_flags);
// remove the SCTP node
uwsgi_log("[0] removing SCTP node %d flags = %d len = %d\n", interesting_fd, msg_flags, len);
uwsgi_fr_sctp_del_node(interesting_fd);
if (ufr.fr_table[interesting_fd]->timeout) {
del_timeout(ufr.fr_table[interesting_fd]);
}
free(ufr.fr_table[interesting_fd]);
ufr.fr_table[interesting_fd] = NULL;
close(interesting_fd);
}
break;
case FASTROUTER_STATUS_SCTP_RESPONSE:
// data from instance
if (interesting_fd == fr_session->instance_fd) {
struct sctp_sndrcvinfo sinfo;
struct uwsgi_header *uh;
int msg_flags = 0;
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
len = sctp_recvmsg(fr_session->instance_fd, fr_session->buffer, 0xffff, NULL, NULL, &sinfo, &msg_flags);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(ufr.fr_table[fr_session->fd]);
// REMOVE THE NODE
uwsgi_log("[1] removing SCTP node %d flags = %d len = %d\n", interesting_fd, msg_flags, len);
uwsgi_fr_sctp_del_node(interesting_fd);
if (ufr.fr_table[interesting_fd]->timeout) {
del_timeout(ufr.fr_table[interesting_fd]);
}
free(ufr.fr_table[interesting_fd]);
ufr.fr_table[interesting_fd] = NULL;
close(interesting_fd);
break;
}
if (fr_session->fd != -1 && sinfo.sinfo_stream != fr_session->fd) {
if (fr_session->fd != -1) {
uwsgi_log("INVALID SCTP STREAM !!!\n");
close_session(ufr.fr_table[fr_session->fd]);
}
break;
}
uh = (struct uwsgi_header *) &sinfo.sinfo_ppid;
// check for close packet
if (uh->modifier1 == 200) {
fr_session->status = FASTROUTER_STATUS_SCTP_NODE_FREE;
if (fr_session->fd != -1) {
close_session(ufr.fr_table[fr_session->fd]);
}
break;
}
if (fr_session->fd == -1) {
break;
}
len = send(fr_session->fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
close_session(ufr.fr_table[fr_session->fd]);
break;
}
// update transfer statistics
if (fr_session->un)
fr_session->un->transferred += len;
}
// body from client
else if (interesting_fd == fr_session->fd) {
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
// mark session as broken
ufr.fr_table[fr_session->instance_fd]->fd = -1;
close_session(fr_session);
break;
}
struct sctp_sndrcvinfo sinfo;
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
// map the stream id to the file descriptor
struct uwsgi_header uh;
uh.modifier1 = 199;
uh.pktsize = 0;
uh.modifier2 = 0;
memcpy(&sinfo.sinfo_ppid, &uh, sizeof(uint32_t));
sinfo.sinfo_stream = fr_session->fd;
len = sctp_send(fr_session->instance_fd, fr_session->buffer, len, &sinfo, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
close_session(fr_session);
break;
}
}
break;
#endif
case FASTROUTER_STATUS_RESPONSE:
// data from instance
if (interesting_fd == fr_session->instance_fd) {
len = recv(fr_session->instance_fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(fr_session);
break;
}
len = send(fr_session->fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
close_session(fr_session);
break;
}
// update transfer statistics
if (fr_session->un)
fr_session->un->transferred += len;
}
// body from client
else if (interesting_fd == fr_session->fd) {
//uwsgi_log("receiving body...\n");
len = recv(fr_session->fd, fr_session->buffer, 0xffff, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(fr_session);
break;
}
len = send(fr_session->instance_fd, fr_session->buffer, len, 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("send()");
close_session(fr_session);
break;
}
}
break;
case FASTROUTER_STATUS_BUFFERING:
len = recv(fr_session->fd, post_tmp_buf, UMIN(0xffff, fr_session->post_remains), 0);
if (len <= 0) {
if (len < 0)
uwsgi_error("recv()");
close_session(fr_session);
break;
}
if (fwrite(post_tmp_buf, len, 1, fr_session->buf_file) != 1) {
uwsgi_error("fwrite()");
close_session(fr_session);
break;
}
fr_session->post_remains -= len;
if (fr_session->post_remains == 0) {
// close the buf_file ASAP
fclose(fr_session->buf_file);
fr_session->buf_file = NULL;
fr_session->pass_fd = is_unix(fr_session->instance_address, fr_session->instance_address_len);
fr_session->instance_fd = uwsgi_connectn(fr_session->instance_address, fr_session->instance_address_len, 0, 1);
if (fr_session->instance_fd < 0) {
fr_session->instance_failed = 1;
close_session(fr_session);
break;
}
fr_session->status = FASTROUTER_STATUS_CONNECTING;
ufr.fr_table[fr_session->instance_fd] = fr_session;
event_queue_add_fd_write(ufr.queue, fr_session->instance_fd);
}
break;
// fallback to destroy !!!
default:
uwsgi_log("unknown event: closing session\n");
close_session(fr_session);
break;
}
}
+190
View File
@@ -0,0 +1,190 @@
#include "../../uwsgi.h"
#include "fr.h"
extern struct uwsgi_server uwsgi;
extern struct uwsgi_fastrouter ufr;
#ifdef UWSGI_SCTP
extern struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes;
extern struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes_current;
#endif
int uwsgi_fr_map_use_void(struct fastrouter_session *fr_session, char **magic_table) {
return 0;
}
int uwsgi_fr_map_use_cache(struct fastrouter_session *fr_session, char **magic_table) {
fr_session->instance_address = uwsgi_cache_get(fr_session->hostname, fr_session->hostname_len, &fr_session->instance_address_len);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
return 0;
}
int uwsgi_fr_map_use_pattern(struct fastrouter_session *fr_session, char **magic_table) {
int tmp_socket_name_len = 0;
magic_table['s'] = uwsgi_concat2n(fr_session->hostname, fr_session->hostname_len, "", 0);
fr_session->tmp_socket_name = magic_sub(ufr.pattern, ufr.pattern_len, &tmp_socket_name_len, magic_table);
free(magic_table['s']);
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = fr_session->tmp_socket_name;
return 0;
}
int uwsgi_fr_map_use_subscription(struct fastrouter_session *fr_session, char **magic_table) {
fr_session->un = uwsgi_get_subscribe_node(&ufr.subscriptions, fr_session->hostname, fr_session->hostname_len, ufr.subscription_regexp);
if (fr_session->un && fr_session->un->len) {
fr_session->instance_address = fr_session->un->name;
fr_session->instance_address_len = fr_session->un->len;
fr_session->modifier1 = fr_session->un->modifier1;
}
else if (ufr.subscriptions == NULL && ufr.cheap && !ufr.i_am_cheap) {
uwsgi_gateway_go_cheap("uWSGI fastrouter", ufr.queue, &ufr.i_am_cheap);
}
return 0;
}
int uwsgi_fr_map_use_base(struct fastrouter_session *fr_session, char **magic_table) {
int tmp_socket_name_len = 0;
fr_session->tmp_socket_name = uwsgi_concat2nn(ufr.base, ufr.base_len, fr_session->hostname, fr_session->hostname_len, &tmp_socket_name_len);
fr_session->instance_address_len = tmp_socket_name_len;
fr_session->instance_address = fr_session->tmp_socket_name;
return 0;
}
int uwsgi_fr_map_use_cs(struct fastrouter_session *fr_session, char **magic_table) {
if (uwsgi.p[ufr.code_string_modifier1]->code_string) {
fr_session->instance_address = uwsgi.p[ufr.code_string_modifier1]->code_string("uwsgi_fastrouter", ufr.code_string_code, ufr.code_string_function, fr_session->hostname, fr_session->hostname_len);
if (fr_session->instance_address) {
fr_session->instance_address_len = strlen(fr_session->instance_address);
char *cs_mod = uwsgi_str_contains(fr_session->instance_address, fr_session->instance_address_len, ',');
if (cs_mod) {
fr_session->modifier1 = uwsgi_str_num(cs_mod + 1, (fr_session->instance_address_len - (cs_mod - fr_session->instance_address)) - 1);
fr_session->instance_address_len = (cs_mod - fr_session->instance_address);
}
}
}
return 0;
}
int uwsgi_fr_map_use_to(struct fastrouter_session *fr_session, char **magic_table) {
fr_session->instance_address = ufr.to_socket->name;
fr_session->instance_address_len = ufr.to_socket->name_len;
return 0;
}
int uwsgi_fr_map_use_static_nodes(struct fastrouter_session *fr_session, char **magic_table) {
if (!ufr.current_static_node) {
ufr.current_static_node = ufr.static_nodes;
}
fr_session->static_node = ufr.current_static_node;
// is it a dead node ?
if (fr_session->static_node->custom > 0) {
// gracetime passed ?
if (fr_session->static_node->custom + ufr.static_node_gracetime <= (uint64_t) uwsgi_now()) {
fr_session->static_node->custom = 0;
}
else {
struct uwsgi_string_list *tmp_node = fr_session->static_node;
struct uwsgi_string_list *next_node = fr_session->static_node->next;
fr_session->static_node = NULL;
// needed for 1-node only setups
if (!next_node)
next_node = ufr.static_nodes;
while (tmp_node != next_node) {
if (!next_node) {
next_node = ufr.static_nodes;
}
if (tmp_node == next_node)
break;
if (next_node->custom == 0) {
fr_session->static_node = next_node;
break;
}
next_node = next_node->next;
}
}
}
if (fr_session->static_node) {
fr_session->instance_address = fr_session->static_node->value;
fr_session->instance_address_len = fr_session->static_node->len;
// set the next one
ufr.current_static_node = fr_session->static_node->next;
}
else {
// set the next one
ufr.current_static_node = ufr.current_static_node->next;
}
return 0;
}
#ifdef UWSGI_SCTP
int uwsgi_fr_map_use_sctp(struct fastrouter_session *fr_session, char **magic_table) {
if (!*uwsgi_fastrouter_sctp_nodes_current)
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes_current;
int choosen_fd = -1;
// find the first available server
while (ufsn) {
if (ufr.fr_table[ufsn->fd]->status == FASTROUTER_STATUS_SCTP_NODE_FREE) {
ufsn->requests++;
choosen_fd = ufsn->fd;
break;
}
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes_current) {
break;
}
ufsn = ufsn->next;
}
// no nodes available
if (choosen_fd == -1) {
fr_session->retry = 1;
del_timeout(fr_session);
fr_session->timeout = add_fake_timeout(fr_session);
return -1;
}
struct sctp_sndrcvinfo sinfo;
memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
memcpy(&sinfo.sinfo_ppid, &fr_session->uh, sizeof(uint32_t));
sinfo.sinfo_stream = fr_session->fd;
ssize_t len = sctp_send(choosen_fd, fr_session->buffer, fr_session->uh.pktsize, &sinfo, 0);
if (len < 0)
uwsgi_error("sctp_send()");
fr_session->instance_fd = choosen_fd;
fr_session->status = FASTROUTER_STATUS_SCTP_RESPONSE;
ufr.fr_table[fr_session->instance_fd]->status = FASTROUTER_STATUS_SCTP_RESPONSE;
ufr.fr_table[fr_session->instance_fd]->fd = fr_session->fd;
// round robin
*uwsgi_fastrouter_sctp_nodes_current = (*uwsgi_fastrouter_sctp_nodes_current)->next;
return -1;
}
#endif
+103
View File
@@ -0,0 +1,103 @@
#ifdef UWSGI_SCTP
#include "../../uwsgi.h"
#include "fr.h"
extern struct uwsgi_fastrouter ufr;
struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes;
struct uwsgi_fr_sctp_node **uwsgi_fastrouter_sctp_nodes_current;
struct uwsgi_fr_sctp_node *uwsgi_fr_sctp_add_node(int fd) {
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes;
if (!ufsn) {
*uwsgi_fastrouter_sctp_nodes = uwsgi_malloc(sizeof(struct uwsgi_fr_sctp_node));
(*uwsgi_fastrouter_sctp_nodes)->next = *uwsgi_fastrouter_sctp_nodes;
(*uwsgi_fastrouter_sctp_nodes)->prev = *uwsgi_fastrouter_sctp_nodes;
(*uwsgi_fastrouter_sctp_nodes)->requests = 0;
(*uwsgi_fastrouter_sctp_nodes)->fd = fd;
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
}
else {
while(ufsn) {
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes) {
break;
}
ufsn = ufsn->next;
}
ufsn->next = uwsgi_malloc(sizeof(struct uwsgi_fr_sctp_node));
ufsn->next->next = *uwsgi_fastrouter_sctp_nodes;
ufsn->next->prev = ufsn;
ufsn->next->requests = 0;
ufsn->next->fd = fd;
(*uwsgi_fastrouter_sctp_nodes)->prev = ufsn->next;
*uwsgi_fastrouter_sctp_nodes_current = ufsn->next;
}
return *uwsgi_fastrouter_sctp_nodes_current;
}
void uwsgi_fr_sctp_del_node(int fd) {
struct uwsgi_fr_sctp_node *ufsn = *uwsgi_fastrouter_sctp_nodes;
while(ufsn) {
if (ufsn->fd == fd) {
struct uwsgi_fr_sctp_node *prev = ufsn->prev;
struct uwsgi_fr_sctp_node *next = ufsn->next;
// am i the only node ?
if (prev == ufsn) {
free(ufsn);
*uwsgi_fastrouter_sctp_nodes = NULL;
*uwsgi_fastrouter_sctp_nodes_current = NULL;
break;
}
prev->next = next;
next->prev = prev;
// am i the first node ?
if (ufsn == *uwsgi_fastrouter_sctp_nodes) {
*uwsgi_fastrouter_sctp_nodes = next;
*uwsgi_fastrouter_sctp_nodes_current = next;
free(ufsn);
break;
}
if (*uwsgi_fastrouter_sctp_nodes_current == ufsn) {
*uwsgi_fastrouter_sctp_nodes_current = *uwsgi_fastrouter_sctp_nodes;
}
free(ufsn);
break;
}
if (ufsn->next == *uwsgi_fastrouter_sctp_nodes) {
break;
}
ufsn = ufsn->next;
}
}
void uwsgi_opt_fastrouter_sctp(char *opt, char *value, void *foobar) {
struct uwsgi_gateway_socket *ugs = uwsgi_new_gateway_socket(value, "uWSGI fastrouter");
ugs->sctp = 1;
ufr.has_sctp_sockets++;
}
#endif
+1 -1
View File
@@ -4,4 +4,4 @@ CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['fastrouter']
GCC_LIST = ['fr_sctp', 'fr_map', 'fastrouter', 'fr_events']
+1 -7
View File
@@ -7,10 +7,6 @@ struct ufib {
VALUE *fib;
} ufiber;
struct option fiber_options[] = {
{ 0, 0, 0, 0 }
};
VALUE uwsgi_fiber_request() {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
@@ -58,14 +54,13 @@ void fiber_loop() {
uwsgi.schedule_to_main = fiber_schedule_to_main;
uwsgi.schedule_to_req = fiber_schedule_to_req;
// must run all the rack/ruby plugins without protection
ur.unprotected = 1;
rb_protect(protected_async_loop, 0, &error);
if (error) {
uwsgi_ruby_exception();
exit(1);
exit(1);
}
// never here
@@ -81,5 +76,4 @@ struct uwsgi_plugin fiber_plugin = {
.name = "fiber",
.init = fiber_init,
.options = fiber_options,
};
+1
View File
@@ -9,6 +9,7 @@ NAME='fiber'
CFLAGS = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['CFLAGS']\"").read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-DRUBY19')
includedir = os.popen(RUBYPATH + " -e \"require 'rbconfig';print Config::CONFIG['rubyhdrdir']\"").read().rstrip()
if includedir == 'nil':
+2 -7
View File
@@ -3,17 +3,13 @@
extern struct uwsgi_server uwsgi;
extern struct uwsgi_python up;
struct option gevent_options[] = {
{ 0, 0, 0, 0 }
};
#define GEVENT_SWITCH PyObject *gswitch = python_call(ugevent.greenlet_switch, ugevent.greenlet_switch_args, 0, NULL); Py_DECREF(gswitch)
#define GET_CURRENT_GREENLET python_call(ugevent.get_current, ugevent.get_current_args, 0, NULL)
#define free_req_queue uwsgi.async_queue_unused_ptr++; uwsgi.async_queue_unused[uwsgi.async_queue_unused_ptr] = uwsgi.wsgi_req
#define stop_the_watchers ret = PyObject_CallMethod(timer, "stop", NULL);\
if (ret) Py_DECREF(ret);\
if (ret) { Py_DECREF(ret); }\
ret = PyObject_CallMethod(watcher, "stop", NULL);\
if (ret) Py_DECREF(ret);
if (ret) { Py_DECREF(ret); }
struct uwsgi_gevent {
PyObject *greenlet_switch;
@@ -352,5 +348,4 @@ struct uwsgi_plugin gevent_plugin = {
.name = "gevent",
.init = gevent_init,
.options = gevent_options,
};
+120
View File
@@ -0,0 +1,120 @@
#include "../../uwsgi.h"
#include <zlib.h>
extern struct uwsgi_server uwsgi;
#define MAX_GELF 8192
struct graylog2_config {
char *host;
char json_buf[MAX_GELF];
char escaped_buf[MAX_GELF];
size_t escaped_len;
char buffer[MAX_GELF];
} g2c;
ssize_t uwsgi_graylog2_logger(struct uwsgi_logger *ul, char *message, size_t len) {
size_t i;
if (!ul->configured) {
if (!uwsgi.choosen_logger_arg) {
uwsgi_log_safe("invalid graylog2 syntax\n");
exit(1);
}
ul->fd = socket(AF_INET, SOCK_DGRAM, 0);
if (ul->fd < 0) {
uwsgi_error_safe("socket()");
exit(1);
}
uwsgi_socket_nb(ul->fd);
char *comma = strchr(uwsgi.choosen_logger_arg, ',');
if (!comma) {
uwsgi_log_safe("invalid graylog2 syntax\n");
exit(1);
}
g2c.host = comma + 1;
*comma = 0;
char *colon = strchr(uwsgi.choosen_logger_arg, ':');
if (!colon) {
uwsgi_log_safe("invalid graylog2 syntax\n");
exit(1);
}
ul->addr_len = socket_to_in_addr(uwsgi.choosen_logger_arg, colon, 0, &ul->addr.sa_in);
*comma = ',';
ul->configured = 1;
}
g2c.escaped_len = 0;
int truncated = 0;
char *ptr = g2c.escaped_buf;
uLongf destLen = MAX_GELF;
for(i=0;i<len;i++) {
if (message[i] == '\\') {
*ptr ++= '\\';
g2c.escaped_len++;
}
else if (message[i] == '"') {
*ptr ++= '\\';
g2c.escaped_len++;
}
*ptr ++= message[i];
g2c.escaped_len++;
if (!truncated) {
if (g2c.escaped_len == 128) {
truncated = 1;
}
else if (g2c.escaped_len > 128) {
truncated = 2;
}
}
}
if (truncated) truncated = 128 - (truncated-1);
else (truncated = g2c.escaped_len);
int rlen = snprintf(g2c.json_buf, MAX_GELF, "{ \"version\": \"1.0\", \"host\": \"%s\", \"short_message\": \"%.*s\", \"full_message\": \"%.*s\", \"timestamp\": %d, \"level\": 5, \"facility\": \"uWSGI-%s\" }",
g2c.host, truncated, g2c.escaped_buf, (int)g2c.escaped_len, g2c.escaped_buf, (int) time(NULL), UWSGI_VERSION);
if (rlen > 0) {
if (compressBound((uLong) rlen) <= MAX_GELF) {
if (compress((Bytef *) g2c.buffer, &destLen, (Bytef *) g2c.json_buf, (uLong) rlen) == Z_OK) {
return sendto(ul->fd, g2c.buffer, destLen, 0, (const struct sockaddr *) &ul->addr, ul->addr_len);
}
}
}
return -1;
}
void uwsgi_graylog2_register() {
uwsgi_register_logger("graylog2", uwsgi_graylog2_logger);
}
int uwsgi_graylog2_init() {
return 0;
}
struct uwsgi_plugin graylog2_plugin = {
.name = "graylog2",
.on_load = uwsgi_graylog2_register,
.init = uwsgi_graylog2_init
};
+6
View File
@@ -0,0 +1,6 @@
NAME='graylog2'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lz']
GCC_LIST = ['graylog2_plugin']
+3 -3
View File
@@ -10,9 +10,9 @@ struct ugreenlet {
PyGreenlet **gl;
} ugl;
struct option greenlet_options[] = {
{"greenlet", no_argument, &ugl.enabled, 1},
{ 0, 0, 0, 0 }
struct uwsgi_option greenlet_options[] = {
{"greenlet", no_argument, 0, "enable greenlet as suspend engine", uwsgi_opt_true, &ugl.enabled, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
PyObject *py_uwsgi_greenlet_request(PyObject * self, PyObject *args) {
+600 -546
View File
File diff suppressed because it is too large Load Diff
+1 -8
View File
@@ -1,16 +1,9 @@
#include "../../uwsgi.h"
#include <jni.h>
#define MAX_CLASSPATH 64
#define LONG_ARGS_JVM_BASE 17000 + (300 * 100)
#define LONG_ARGS_JVM_CLASS LONG_ARGS_JVM_BASE + 1
#define LONG_ARGS_JVM_CLASSPATH LONG_ARGS_JVM_BASE + 2
struct uwsgi_jvm {
char *classpath[MAX_CLASSPATH];
int classpath_cnt;
struct uwsgi_string_list *classpath;
JNIEnv *env;
char *class;
+10 -30
View File
@@ -5,13 +5,15 @@
with javap -s -p <class>
you can get method signatures
This plugin is the core for all of the JVM-based ones
*/
struct uwsgi_jvm ujvm;
struct option uwsgi_jvm_options[] = {
{"jvm-main-class", required_argument, 0, LONG_ARGS_JVM_CLASS},
{"jvm-classpath", required_argument, 0, LONG_ARGS_JVM_CLASSPATH},
struct uwsgi_option uwsgi_jvm_options[] = {
{"jvm-main-class", required_argument, 0, "load the specified class", uwsgi_opt_set_str, &ujvm.class, 0},
{"jvm-classpath", required_argument, 0, "add the specified directory to the classpath", uwsgi_opt_add_string_list, &ujvm.classpath, 0},
{0, 0, 0, 0},
};
@@ -87,7 +89,6 @@ int jvm_init(void) {
JavaVMOption options[1];
jmethodID mmid;
int i;
char *old_cp = NULL ;
@@ -97,17 +98,17 @@ int jvm_init(void) {
options[0].optionString = "-Djava.class.path=.";
if (ujvm.classpath_cnt > 0) {
for(i=0;i<ujvm.classpath_cnt;i++) {
struct uwsgi_string_list *cp = ujvm.classpath;
while(cp) {
if (old_cp) {
options[0].optionString = uwsgi_concat3(old_cp, ":", ujvm.classpath[i]);
options[0].optionString = uwsgi_concat3(old_cp, ":", cp->value);
free(old_cp);
}
else {
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", ujvm.classpath[i]);
options[0].optionString = uwsgi_concat3(options[0].optionString, ":", cp->value);
}
old_cp = options[0].optionString ;
}
cp = cp->next;
}
vm_args.options = options;
@@ -199,32 +200,11 @@ int uwsgi_jvm_strlen2c(jobject obj) {
return (*ujvm.env)->GetStringUTFLength(ujvm.env, obj);
}
int uwsgi_jvm_manage_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_JVM_CLASS:
ujvm.class = optarg;
return 1;
case LONG_ARGS_JVM_CLASSPATH:
if (ujvm.classpath_cnt < MAX_CLASSPATH) {
ujvm.classpath[ujvm.classpath_cnt] = optarg;
ujvm.classpath_cnt++;
}
else {
uwsgi_log( "you can specify at most %d --jvm-classpath options\n", MAX_CLASSPATH);
}
return 1;
}
return 0;
}
struct uwsgi_plugin jvm_plugin = {
.name = "jvm",
.init = jvm_init,
.options = uwsgi_jvm_options,
.manage_opt = uwsgi_jvm_manage_opt,
};
+2 -2
View File
@@ -13,8 +13,8 @@ NAME='jvm'
# UWSGICONFIG_JVM_INCPATH="/usr/java/include -I /usr/java/include/solaris" UWSGICONFIG_JVM_LIBPATH="/usr/java/jre/lib/i386/" python uwsgiconfig.py --plugin plugins/jvm
# Ubuntu
JVM_INCPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/include/ -I/usr/lib/jvm/java-6-sun-1.6.0.15/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-sun-1.6.0.15/jre/lib/i386/server/"
JVM_INCPATH = "/usr/lib/jvm/java-6-openjdk/include/ -I/usr/lib/jvm/java-6-openjdk/include/linux"
JVM_LIBPATH = "/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server/"
try:
JVM_INCPATH = os.environ['UWSGICONFIG_JVM_INCPATH']
+73
View File
@@ -0,0 +1,73 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
ssize_t uwsgi_socket_logger(struct uwsgi_logger *ul, char *message, size_t len) {
int family = AF_UNIX;
if (!ul->configured) {
char *comma = strchr(uwsgi.choosen_logger_arg, ',');
if (comma) {
ul->data = comma+1;
*comma = 0;
}
char *colon = strchr(uwsgi.choosen_logger_arg, ':');
if (colon) {
family = AF_INET;
ul->addr_len = socket_to_in_addr(uwsgi.choosen_logger_arg, colon, 0, &ul->addr.sa_in);
}
else {
ul->addr_len = socket_to_un_addr(uwsgi.choosen_logger_arg, &ul->addr.sa_un);
}
ul->fd = socket(family, SOCK_DGRAM, 0);
if (ul->fd < 0) {
uwsgi_error_safe("socket()");
exit(1);
}
memset(&ul->msg, 0, sizeof(struct msghdr));
ul->msg.msg_name = &ul->addr;
ul->msg.msg_namelen = ul->addr_len;
if (ul->data) {
ul->msg.msg_iov = uwsgi_malloc(sizeof(struct iovec) * 2);
ul->msg.msg_iov[0].iov_base = ul->data;
ul->msg.msg_iov[0].iov_len = strlen(ul->data);
ul->msg.msg_iovlen = 2;
ul->count = 1;
}
else {
ul->msg.msg_iov = uwsgi_malloc(sizeof(struct iovec));
ul->msg.msg_iovlen = 1;
}
if (comma) {
*comma = ',' ;
}
ul->configured = 1;
}
ul->msg.msg_iov[ul->count].iov_base = message;
ul->msg.msg_iov[ul->count].iov_len = len;
return sendmsg(ul->fd, &ul->msg, 0);
}
void uwsgi_logsocket_register() {
uwsgi_register_logger("socket", uwsgi_socket_logger);
}
struct uwsgi_plugin logsocket_plugin = {
.name = "logsocket",
.on_load = uwsgi_logsocket_register,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='logsocket'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['logsocket_plugin']
+4 -18
View File
@@ -12,14 +12,11 @@ struct uwsgi_lua {
char *filename;
} ulua;
#define LONG_ARGS_LUA_BASE 17000 + (6 * 100)
#define LONG_ARGS_LUA LONG_ARGS_LUA_BASE + 1
#define lca(L, n) ulua_check_args(L, __FUNCTION__, n)
struct option uwsgi_lua_options[] = {
struct uwsgi_option uwsgi_lua_options[] = {
{"lua", required_argument, 0, LONG_ARGS_LUA},
{"lua", required_argument, 0, "load lua wsapi app", uwsgi_opt_set_str, &ulua.filename, 0},
{0, 0, 0, 0},
@@ -583,16 +580,6 @@ void uwsgi_lua_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
}
int uwsgi_lua_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_LUA:
ulua.filename = optarg;
return 1;
}
return 0;
}
int uwsgi_lua_magic(char *mountpoint, char *lazy) {
@@ -682,7 +669,7 @@ int uwsgi_lua_signal_handler(uint8_t sig, void *handler) {
}
uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) {
uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
uint8_t i;
const char *sv;
@@ -698,7 +685,7 @@ uint16_t uwsgi_lua_rpc(void * func, uint8_t argc, char **argv, char *buffer) {
lua_rawgeti(L, LUA_REGISTRYINDEX, ifunc);
for(i=0;i<argc;i++) {
lua_pushstring(L, argv[i]);
lua_pushlstring(L, argv[i], argvs[i]);
}
if (lua_pcall(L, argc, 1, 0) != 0) {
@@ -726,7 +713,6 @@ struct uwsgi_plugin lua_plugin = {
.modifier1 = 6,
.init = uwsgi_lua_init,
.options = uwsgi_lua_options,
.manage_opt = uwsgi_lua_manage_options,
.request = uwsgi_lua_request,
.after_request = uwsgi_lua_after_request,
.init_apps = uwsgi_lua_app,
+21 -37
View File
@@ -3,61 +3,58 @@
extern struct uwsgi_server uwsgi;
int use_nagios = 0;
#define LONG_ARGS_NAGIOS 40000
struct uwsgi_option nagios_options[] = {
struct option nagios_options[] = {
{"nagios", no_argument, 0, LONG_ARGS_NAGIOS},
{0, 0, 0, 0},
{"nagios", no_argument, 0, "nagios check", uwsgi_opt_true, &use_nagios, UWSGI_OPT_NO_INITIAL},
{0, 0, 0, 0, 0, 0, 0},
};
int nagios() {
char *tcp_port;
struct wsgi_request nagios_req;
// connect and send
struct uwsgi_header uh;
char *buf = NULL;
if (!use_nagios) {
return 1;
}
if (!uwsgi.sockets) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port = strchr(uwsgi.sockets->name, ':');
if (tcp_port == NULL) {
fprintf(stdout, "UWSGI UNKNOWN: you have specified an invalid socket\n");
exit(3);
}
tcp_port[0] = 0;
int fd = connect_to_tcp(uwsgi.sockets->name, atoi(tcp_port + 1), uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
int fd = uwsgi_connect(uwsgi.sockets->name, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) {
fprintf(stdout, "UWSGI CRITICAL: could not connect() to workers\n");
exit(2);
}
nagios_req.uh.modifier1 = UWSGI_MODIFIER_PING;
nagios_req.uh.pktsize = 0;
nagios_req.uh.modifier2 = 0;
if (write(fd, &nagios_req.uh, 4) != 4) {
uh.modifier1 = UWSGI_MODIFIER_PING;
uh.pktsize = 0;
uh.modifier2 = 0;
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
fprintf(stdout, "UWSGI CRITICAL: could not send ping packet to workers\n");
exit(2);
}
nagios_req.poll.fd = fd;
nagios_req.poll.events = POLLIN;
if (!uwsgi_parse_packet(&nagios_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
int ret = uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buf);
if (ret == -2) {
fprintf(stdout, "UWSGI CRITICAL: timed out waiting for response\n");
exit(2);
}
else if (ret == -1) {
fprintf(stdout, "UWSGI CRITICAL: error reading response\n");
exit(2);
}
else {
if (nagios_req.uh.pktsize > 0) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", nagios_req.uh.pktsize, nagios_req.buffer);
if (uh.pktsize > 0 && buf) {
fprintf(stdout, "UWSGI WARNING: %.*s\n", uh.pktsize, buf);
exit(1);
}
else {
@@ -71,21 +68,8 @@ int nagios() {
exit(3);
}
int nagios_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_NAGIOS:
uwsgi.no_initial_output = 1;
use_nagios = 1;
return 1;
}
return 0;
}
struct uwsgi_plugin nagios_plugin = {
.options = nagios_options,
.manage_opt = nagios_opt,
.init = nagios,
};
+35
View File
@@ -0,0 +1,35 @@
#include "../../uwsgi.h"
int uwsgi_request_notfound(struct wsgi_request *wsgi_req) {
struct iovec iov[3];
if (wsgi_req->protocol_len > 0) {
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
}
else {
iov[0].iov_base = "HTTP/1.0";
iov[0].iov_len = 8;
}
iov[1].iov_base = " 404 Not Found\r\n";
iov[1].iov_len = 16;
iov[2].iov_base = "Content-Type: text/plain\r\n\r\n";
iov[2].iov_len = 28;
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, iov, 3);
wsgi_req->response_size = wsgi_req->socket->proto_write(wsgi_req, "Not Found", 9);
wsgi_req->status = 404;
return UWSGI_OK;
}
struct uwsgi_plugin notfound_plugin = {
.name = "notfound",
.request = uwsgi_request_notfound,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='notfound'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['notfound']
+893
View File
@@ -0,0 +1,893 @@
#include "php.h"
#include "SAPI.h"
#include "php_main.h"
#include "php_variables.h"
#include "ext/standard/php_smart_str.h"
#include "ext/standard/info.h"
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
// http status codes list
extern struct http_status_codes hsc[];
static sapi_module_struct uwsgi_sapi_module;
struct uwsgi_php {
struct uwsgi_string_list *allowed_docroot;
struct uwsgi_string_list *allowed_ext;
struct uwsgi_string_list *index;
struct uwsgi_string_list *set;
char *docroot;
char *app;
size_t ini_size;
char *server_software;
size_t server_software_len;
} uphp;
void uwsgi_opt_php_ini(char *opt, char *value, void *foobar) {
uwsgi_sapi_module.php_ini_path_override = uwsgi_str(value);
uwsgi_sapi_module.php_ini_ignore = 1;
}
struct uwsgi_option uwsgi_php_options[] = {
{"php-ini", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
{"php-config", required_argument, 0, "set php.ini path", uwsgi_opt_php_ini, NULL, 0},
{"php-set", required_argument, 0, "set a php config directive", uwsgi_opt_add_string_list, &uphp.set, 0},
{"php-index", required_argument, 0, "list the php index files", uwsgi_opt_add_string_list, &uphp.index, 0},
{"php-docroot", required_argument, 0, "force php DOCUMENT_ROOT", uwsgi_opt_set_str, &uphp.docroot, 0},
{"php-allowed-docroot", required_argument, 0, "list the allowed document roots", uwsgi_opt_add_string_list, &uphp.allowed_docroot, 0},
{"php-allowed-ext", required_argument, 0, "list the allowed php file extensions", uwsgi_opt_add_string_list, &uphp.allowed_ext, 0},
{"php-server-software", required_argument, 0, "force php SERVER_SOFTWARE", uwsgi_opt_set_str, &uphp.server_software, 0},
{"php-app", required_argument, 0, "force the php file to run at each request", uwsgi_opt_set_str, &uphp.app, 0},
{0, 0, 0, 0, 0, 0, 0},
};
void uwsgi_php_redirect_to_slash(struct wsgi_request *wsgi_req) {
struct iovec iov[6];
wsgi_req->status = 301;
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
iov[1].iov_base = " 301 Moved Permanently\r\n";
iov[1].iov_len = 24;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
iov[0].iov_base = "Location: ";
iov[0].iov_len = 10;
iov[1].iov_base = wsgi_req->path_info;
iov[1].iov_len = wsgi_req->path_info_len;
iov[2].iov_base = "/";
iov[2].iov_len = 1;
if (wsgi_req->query_string_len > 0) {
iov[3].iov_base = "?";
iov[3].iov_len = 1;
iov[4].iov_base = wsgi_req->query_string;
iov[4].iov_len = wsgi_req->query_string_len;
iov[5].iov_base = "\r\n\r\n";
iov[5].iov_len = 4;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
wsgi_req->header_cnt++;
}
else {
iov[3].iov_base = "\r\n\r\n";
iov[3].iov_len = 4;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
wsgi_req->header_cnt++;
}
}
static int sapi_uwsgi_ub_write(const char *str, uint str_length TSRMLS_DC)
{
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
ssize_t len = wsgi_req->socket->proto_write(wsgi_req, (char *) str, str_length);
if (len != (ssize_t) str_length) {
php_handle_aborted_connection();
return -1;
}
wsgi_req->response_size += len;
return str_length;
}
void uwsgi_php_404(struct wsgi_request *wsgi_req) {
wsgi_req->status = 404;
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 404 Not Found\r\nContent-Type: text/plain\r\n\r\nNot Found", 61);
}
void uwsgi_php_403(struct wsgi_request *wsgi_req) {
wsgi_req->status = 403;
wsgi_req->headers_size += wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.0 403 Forbidden\r\nContent-Type: text/plain\r\n\r\nForbidden", 61);
}
static int sapi_uwsgi_send_headers(sapi_headers_struct *sapi_headers)
{
sapi_header_struct *h;
zend_llist_position pos;
struct iovec iov[6];
char status[4];
struct http_status_codes *http_sc;
if (SG(request_info).no_headers == 1) {
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
wsgi_req->status = SG(sapi_headers).http_response_code;
if (!wsgi_req->status) wsgi_req->status = 200;
if (!SG(sapi_headers).http_status_line) {
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
iov[1].iov_base = " ";
iov[1].iov_len = 1;
uwsgi_num2str2n(wsgi_req->status, status, 4);
iov[2].iov_base = status;
iov[2].iov_len = 3;
iov[3].iov_base = " ";
iov[3].iov_len = 1;
// get the status code
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
if (!strncmp(http_sc->key, status, 3)) {
iov[4].iov_base = (char *) http_sc->message;
iov[4].iov_len = http_sc->message_size;
break;
}
}
if (iov[4].iov_len == 0) {
iov[4].iov_base = "Unknown";
iov[4].iov_len = 7;
}
iov[5].iov_base = "\r\n";
iov[5].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 6);
}
else {
iov[0].iov_base = SG(sapi_headers).http_status_line;
iov[0].iov_len = strlen(iov[0].iov_base);
iov[1].iov_base = "\r\n";
iov[1].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
}
h = zend_llist_get_first_ex(&sapi_headers->headers, &pos);
while (h) {
iov[0].iov_base = h->header;
iov[0].iov_len = h->header_len;
iov[1].iov_base = "\r\n";
iov[1].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
wsgi_req->header_cnt++;
h = zend_llist_get_next_ex(&sapi_headers->headers, &pos);
}
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
static int sapi_uwsgi_read_post(char *buffer, uint count_bytes TSRMLS_DC)
{
uint read_bytes = 0;
size_t len;
int fd = -1;
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
if (wsgi_req->body_as_file) {
fd = fileno((FILE *)wsgi_req->async_post);
}
else if (uwsgi.post_buffering > 0) {
if (wsgi_req->post_cl > (size_t) uwsgi.post_buffering) {
fd = fileno((FILE *)wsgi_req->async_post);
}
}
else {
fd = wsgi_req->poll.fd;
}
count_bytes = MIN(count_bytes, wsgi_req->post_cl - SG(read_post_bytes));
// data in memory
if (fd == -1) {
if (count_bytes > 0) {
memcpy(buffer, wsgi_req->post_buffering_buf + wsgi_req->post_pos, count_bytes);
wsgi_req->post_pos += count_bytes;
}
return count_bytes;
}
while (read_bytes < count_bytes) {
len = read(fd, buffer + read_bytes, count_bytes - read_bytes);
if (len <= 0) {
break;
}
read_bytes += len;
}
return read_bytes;
}
static char *sapi_uwsgi_read_cookies(void)
{
uint16_t len = 0;
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
char *cookie = uwsgi_get_var(wsgi_req, (char *)"HTTP_COOKIE", 11, &len);
if (cookie) {
return estrndup(cookie, len);
}
return NULL;
}
static void sapi_uwsgi_register_variables(zval *track_vars_array TSRMLS_DC)
{
int i;
struct wsgi_request *wsgi_req = (struct wsgi_request *) SG(server_context);
php_import_environment_variables(track_vars_array TSRMLS_CC);
if (uphp.server_software) {
if (!uphp.server_software_len) uphp.server_software_len = strlen(uphp.server_software);
php_register_variable_safe("SERVER_SOFTWARE", uphp.server_software, uphp.server_software_len, track_vars_array TSRMLS_CC);
}
else {
php_register_variable_safe("SERVER_SOFTWARE", "uWSGI", 5, track_vars_array TSRMLS_CC);
}
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
php_register_variable_safe( estrndup(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len,
track_vars_array TSRMLS_CC);
}
php_register_variable_safe("PATH_INFO", wsgi_req->path_info, wsgi_req->path_info_len, track_vars_array TSRMLS_CC);
php_register_variable_safe("SCRIPT_NAME", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
php_register_variable_safe("SCRIPT_FILENAME", wsgi_req->file, wsgi_req->file_len, track_vars_array TSRMLS_CC);
php_register_variable_safe("DOCUMENT_ROOT", wsgi_req->document_root, wsgi_req->document_root_len, track_vars_array TSRMLS_CC);
if (wsgi_req->path_info_len) {
char *path_translated = ecalloc(1, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len + 1);
memcpy(path_translated, wsgi_req->file, (wsgi_req->file_len - wsgi_req->script_name_len));
memcpy(path_translated + (wsgi_req->file_len - wsgi_req->script_name_len), wsgi_req->path_info, wsgi_req->path_info_len);
php_register_variable_safe("PATH_TRANSLATED", path_translated, (wsgi_req->file_len - wsgi_req->script_name_len) + wsgi_req->path_info_len , track_vars_array TSRMLS_CC);
}
else {
php_register_variable_safe("PATH_TRANSLATED", "", 0, track_vars_array TSRMLS_CC);
}
php_register_variable_safe("PHP_SELF", wsgi_req->script_name, wsgi_req->script_name_len, track_vars_array TSRMLS_CC);
}
static sapi_module_struct uwsgi_sapi_module;
void uwsgi_php_set(char *opt) {
uwsgi_sapi_module.ini_entries = realloc(uwsgi_sapi_module.ini_entries, uphp.ini_size + strlen(opt)+2);
memcpy(uwsgi_sapi_module.ini_entries + uphp.ini_size, opt, strlen(opt));
uphp.ini_size += strlen(opt)+1;
uwsgi_sapi_module.ini_entries[uphp.ini_size-1] = '\n';
uwsgi_sapi_module.ini_entries[uphp.ini_size] = 0;
}
// future implementation...
PHP_MINIT_FUNCTION(uwsgi_php_minit) {
return SUCCESS;
}
PHP_FUNCTION(uwsgi_version) {
RETURN_STRING(UWSGI_VERSION, 1);
}
PHP_FUNCTION(uwsgi_worker_id) {
RETURN_LONG(uwsgi.mywid);
}
PHP_FUNCTION(uwsgi_masterpid) {
if (uwsgi.master_process) {
RETURN_LONG(uwsgi.workers[0].pid);
}
RETURN_LONG(0);
}
PHP_FUNCTION(uwsgi_cache_del) {
char *key = NULL;
int keylen = 0;
if (!uwsgi.cache_max_items)
RETURN_NULL();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &keylen) == FAILURE) {
RETURN_NULL();
}
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_del(key, keylen)) {
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_TRUE;
}
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_cache_get) {
char *key = NULL;
int keylen = 0;
uint64_t valsize;
if (!uwsgi.cache_max_items)
RETURN_NULL();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &key, &keylen) == FAILURE) {
RETURN_NULL();
}
uwsgi_rlock(uwsgi.cache_lock);
char *value = uwsgi_cache_get(key, keylen, &valsize);
if (value) {
char *ret = estrndup(value, valsize);
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_STRING(ret, 0);
}
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_cache_set) {
char *key = NULL;
int keylen;
char *value = NULL;
int vallen;
uint64_t expires = 0;
if (!uwsgi.cache_max_items)
RETURN_NULL();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &key, &keylen, &value, &vallen, &expires) == FAILURE) {
RETURN_NULL();
}
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
RETURN_NULL();
}
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_set(key, keylen, value, vallen, expires, 0)) {
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_TRUE;
}
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_cache_update) {
char *key = NULL;
int keylen;
char *value = NULL;
int vallen;
uint64_t expires = 0;
if (!uwsgi.cache_max_items)
RETURN_NULL();
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|l", &key, &keylen, &value, &vallen, &expires) == FAILURE) {
RETURN_NULL();
}
if ((uint64_t)vallen > uwsgi.cache_blocksize) {
RETURN_NULL();
}
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi_cache_set(key, keylen, value, vallen, expires, UWSGI_CACHE_FLAG_UPDATE)) {
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_TRUE;
}
uwsgi_rwunlock(uwsgi.cache_lock);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_rpc) {
int num_args = 0;
int i;
char *node = NULL;
char *func = NULL;
zval ***varargs = NULL;
zval *z_current_obj;
char *argv[256];
uint16_t argvs[256];
uint16_t size = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "+", &varargs, &num_args) == FAILURE) {
RETURN_NULL();
}
if (num_args < 2)
goto clear;
if (num_args > 256 + 2)
goto clear;
z_current_obj = *varargs[0];
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
goto clear;
}
node = Z_STRVAL_P(z_current_obj);
z_current_obj = *varargs[1];
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
goto clear;
}
func = Z_STRVAL_P(z_current_obj);
for(i=0;i<(num_args-2);i++) {
z_current_obj = *varargs[i+2];
if (Z_TYPE_P(z_current_obj) != IS_STRING) {
goto clear;
}
argv[i] = Z_STRVAL_P(z_current_obj);
argvs[i] = Z_STRLEN_P(z_current_obj);
}
char *response = uwsgi_do_rpc(node, func, num_args - 2, argv, argvs, &size);
if (size > 0) {
// here we do not free varargs for performance reasons
char *ret = estrndup(response, size);
free(response);
RETURN_STRING(ret, 0);
}
clear:
efree(varargs);
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_setprocname) {
char *name;
int name_len;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &name, &name_len) == FAILURE) {
RETURN_NULL();
}
uwsgi_set_processname(estrndup(name, name_len));
RETURN_NULL();
}
PHP_FUNCTION(uwsgi_signal) {
long long_signum;
uint8_t signum = 0;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &long_signum) == FAILURE) {
RETURN_NULL();
}
signum = (uint8_t) long_signum;
uwsgi_signal_send(uwsgi.signal_socket, signum);
RETURN_NULL();
}
zend_function_entry uwsgi_php_functions[] = {
PHP_FE(uwsgi_version, NULL)
PHP_FE(uwsgi_setprocname, NULL)
PHP_FE(uwsgi_worker_id, NULL)
PHP_FE(uwsgi_masterpid, NULL)
PHP_FE(uwsgi_signal, NULL)
PHP_FE(uwsgi_rpc, NULL)
PHP_FE(uwsgi_cache_get, NULL)
PHP_FE(uwsgi_cache_set, NULL)
PHP_FE(uwsgi_cache_update, NULL)
PHP_FE(uwsgi_cache_del, NULL)
{ NULL, NULL, NULL},
};
PHP_MINFO_FUNCTION(uwsgi_php_minfo) {
php_info_print_table_start( );
php_info_print_table_row(2, "uwsgi api", "enabled");
if (uwsgi.cache_max_items > 0) {
php_info_print_table_row(2, "uwsgi cache", "enabled");
}
else {
php_info_print_table_row(2, "uwsgi cache", "disabled");
}
php_info_print_table_end( );
}
static zend_module_entry uwsgi_module_entry = {
STANDARD_MODULE_HEADER,
"uwsgi",
uwsgi_php_functions,
PHP_MINIT(uwsgi_php_minit),
NULL,
NULL,
NULL,
PHP_MINFO(uwsgi_php_minfo),
UWSGI_VERSION,
STANDARD_MODULE_PROPERTIES
};
static int php_uwsgi_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(&uwsgi_sapi_module, &uwsgi_module_entry, 1)==FAILURE) {
return FAILURE;
} else {
return SUCCESS;
}
}
static void sapi_uwsgi_log_message(char *message) {
uwsgi_log("%s\n", message);
}
static sapi_module_struct uwsgi_sapi_module = {
"uwsgi",
"uWSGI/php",
php_uwsgi_startup,
php_module_shutdown_wrapper,
NULL, /* activate */
NULL, /* deactivate */
sapi_uwsgi_ub_write,
NULL,
NULL, /* get uid */
NULL, /* getenv */
php_error,
NULL,
sapi_uwsgi_send_headers,
NULL,
sapi_uwsgi_read_post,
sapi_uwsgi_read_cookies,
sapi_uwsgi_register_variables,
sapi_uwsgi_log_message, /* Log message */
NULL, /* Get request time */
NULL, /* Child terminate */
STANDARD_SAPI_MODULE_PROPERTIES
};
int uwsgi_php_init(void) {
struct http_status_codes *http_sc;
struct uwsgi_string_list *pset = uphp.set;
sapi_startup(&uwsgi_sapi_module);
// applying custom options
while(pset) {
uwsgi_php_set(pset->value);
pset = pset->next;
}
uwsgi_sapi_module.startup(&uwsgi_sapi_module);
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = strlen(http_sc->message);
}
uwsgi_log("PHP %s initialized\n", PHP_VERSION);
return 0;
}
int uwsgi_php_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, char **path_info) {
// and now start walking...
uint16_t i;
char *ptr = wsgi_req->path_info;
char *dst = full_path+docroot_len;
char *part = ptr;
int part_size = 0;
struct stat st;
if (wsgi_req->path_info_len == 0) return 0;
if (ptr[0] == '/') part_size++;
for(i=0;i<wsgi_req->path_info_len;i++) {
if (ptr[i] == '/') {
memcpy(dst, part, part_size-1);
*(dst+part_size-1) = 0;
if (stat(full_path, &st)) {
uwsgi_php_404(wsgi_req);
return -1;
}
// not a directory, stop walking
if (!S_ISDIR(st.st_mode)) {
if (i < (wsgi_req->path_info_len)-1) {
*path_info = ptr + i;
}
return 0;
}
// check for buffer overflow !!!
*(dst+part_size-1) = '/';
*(dst+part_size) = 0;
dst += part_size ;
part_size = 0;
part = ptr + i + 1;
}
part_size++;
}
if (part < wsgi_req->path_info+wsgi_req->path_info_len) {
memcpy(dst, part, part_size-1);
*(dst+part_size-1) = 0;
}
return 0;
}
int uwsgi_php_request(struct wsgi_request *wsgi_req) {
char real_filename[PATH_MAX+1];
char *path_info = NULL;
size_t real_filename_len = 0;
struct stat php_stat;
zend_file_handle file_handle;
SG(server_context) = (void *) wsgi_req;
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
if (uphp.docroot) {
wsgi_req->document_root = uphp.docroot;
wsgi_req->document_root_len = strlen(wsgi_req->document_root);
}
// fallback to cwd
else if (!wsgi_req->document_root_len) {
wsgi_req->document_root = uwsgi.cwd;
wsgi_req->document_root_len = strlen(uwsgi.cwd);
}
if (uphp.app) {
strcpy(real_filename, uphp.app);
wsgi_req->path_info = "";
wsgi_req->path_info_len = 0;
goto secure2;
}
char *filename = uwsgi_concat4n(wsgi_req->document_root, wsgi_req->document_root_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
if (uwsgi_php_walk(wsgi_req, filename, wsgi_req->document_root, wsgi_req->document_root_len, &path_info)) {
free(filename);
return -1;
}
char *orig_path_info = wsgi_req->path_info;
uint16_t orig_path_info_len = wsgi_req->path_info_len;
if (path_info) {
wsgi_req->path_info = path_info;
wsgi_req->path_info_len = orig_path_info_len - (path_info - orig_path_info);
}
else {
wsgi_req->path_info = "";
wsgi_req->path_info_len = 0;
}
if (!realpath(filename, real_filename)) {
free(filename);
uwsgi_php_404(wsgi_req);
return -1;
}
free(filename);
real_filename_len = strlen(real_filename);
if (uphp.allowed_docroot) {
struct uwsgi_string_list *usl = uphp.allowed_docroot;
while(usl) {
if (!uwsgi_starts_with(real_filename, real_filename_len, usl->value, usl->len)) {
goto secure;
}
usl = usl->next;
}
uwsgi_php_403(wsgi_req);
uwsgi_log("PHP security error: %s is not under an allowed docroot\n", real_filename);
return -1;
}
secure:
if (stat(real_filename, &php_stat)) {
uwsgi_php_404(wsgi_req);
return UWSGI_OK;
}
if (S_ISDIR(php_stat.st_mode)) {
// add / to directories
if (orig_path_info_len == 0 || (orig_path_info_len > 0 && orig_path_info[orig_path_info_len-1] != '/')) {
wsgi_req->path_info = orig_path_info;
wsgi_req->path_info_len = orig_path_info_len;
uwsgi_php_redirect_to_slash(wsgi_req);
return UWSGI_OK;
}
struct uwsgi_string_list *upi = uphp.index;
real_filename[real_filename_len] = '/';
real_filename_len++;
int found = 0;
while(upi) {
if (real_filename_len + upi->len + 1 < PATH_MAX) {
// add + 1 to ensure null byte
memcpy(real_filename+real_filename_len, upi->value, upi->len + 1);
if (!access(real_filename, R_OK)) {
found = 1;
break;
}
}
upi = upi->next;
}
if (!found) {
uwsgi_php_404(wsgi_req);
return UWSGI_OK;
}
real_filename_len = strlen(real_filename);
}
if (uphp.allowed_ext) {
struct uwsgi_string_list *usl = uphp.allowed_ext;
while(usl) {
if (real_filename_len >= usl->len) {
if (!uwsgi_strncmp(real_filename+(real_filename_len-usl->len), usl->len, usl->value, usl->len)) {
goto secure2;
}
}
usl = usl->next;
}
uwsgi_php_403(wsgi_req);
uwsgi_log("PHP security error: %s does not end with an allowed extension\n", real_filename);
return -1;
}
secure2:
wsgi_req->file = real_filename;
wsgi_req->file_len = strlen(wsgi_req->file);
if (wsgi_req->document_root[wsgi_req->document_root_len-1] == '/') {
wsgi_req->script_name = real_filename + (wsgi_req->document_root_len-1);
}
else {
wsgi_req->script_name = real_filename + wsgi_req->document_root_len;
}
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
#ifdef UWSGI_DEBUG
uwsgi_log("php filename = %s %.*s\n", real_filename, wsgi_req->script_name_len, wsgi_req->script_name);
#endif
// now check for allowed paths and extensions
SG(request_info).request_uri = estrndup(wsgi_req->uri, wsgi_req->uri_len);
SG(request_info).request_method = estrndup(wsgi_req->method, wsgi_req->method_len);
SG(request_info).proto_num = 1001;
SG(request_info).query_string = estrndup(wsgi_req->query_string, wsgi_req->query_string_len);
SG(request_info).content_length = wsgi_req->post_cl;
SG(request_info).content_type = estrndup(wsgi_req->content_type, wsgi_req->content_type_len);
// reinitialize it at every request !!!
SG(sapi_headers).http_response_code = 200;
SG(request_info).path_translated = wsgi_req->file;
file_handle.type = ZEND_HANDLE_FILENAME;
file_handle.filename = real_filename;
file_handle.free_filename = 0;
file_handle.opened_path = NULL;
if (php_request_startup(TSRMLS_C) == FAILURE) {
internal_server_error(wsgi_req, "unable to start php request");
return -1;
}
php_execute_script(&file_handle TSRMLS_CC);
php_request_shutdown(NULL);
return 0;
}
void uwsgi_php_after_request(struct wsgi_request *wsgi_req) {
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING])
log_request(wsgi_req);
}
SAPI_API struct uwsgi_plugin php_plugin = {
.name = "php",
.modifier1 = 14,
.init = uwsgi_php_init,
.request = uwsgi_php_request,
.after_request = uwsgi_php_after_request,
.options = uwsgi_php_options,
};
+29
View File
@@ -0,0 +1,29 @@
import os
NAME='php'
ld_run_path = None
PHPPATH = 'php-config'
try:
phpdir = os.environ['UWSGICONFIG_PHPDIR']
ld_run_path = "%s/lib" % phpdir
PHPPATH = "%s/bin/php-config" % phpdir
except:
pass
try:
PHPPATH = os.environ['UWSGICONFIG_PHPPATH']
except:
pass
CFLAGS = [os.popen(PHPPATH + ' --includes').read().rstrip()]
LDFLAGS = os.popen(PHPPATH + ' --ldflags').read().rstrip().split()
if ld_run_path:
LDFLAGS.append('-L%s' % ld_run_path)
os.environ['LD_RUN_PATH'] = ld_run_path
LIBS = [os.popen(PHPPATH + ' --libs').read().rstrip(), '-lphp5']
GCC_LIST = ['php_plugin']
+15 -34
View File
@@ -7,16 +7,16 @@ struct uwsgi_ping {
int ping_timeout;
} uping;
struct option uwsgi_ping_options[] = {
{"ping", required_argument, 0, LONG_ARGS_PING},
{"ping-timeout", required_argument, 0, LONG_ARGS_PING_TIMEOUT},
{ 0, 0, 0, 0 }
struct uwsgi_option uwsgi_ping_options[] = {
{"ping", required_argument, 0, "ping specified uwsgi host", uwsgi_opt_set_str, &uping.ping, UWSGI_OPT_NO_INITIAL | UWSGI_OPT_NO_SERVER},
{"ping-timeout", required_argument, 0, "set ping timeout", uwsgi_opt_set_int, &uping.ping_timeout, 0},
{ 0, 0, 0, 0, 0, 0, 0 }
};
static void ping() {
struct wsgi_request ping_req;
char *buf = uwsgi_malloc(uwsgi.buffer_size);
struct uwsgi_header uh;
char *buf = NULL;
// use a 3 secs timeout by default
if (!uping.ping_timeout) uping.ping_timeout = 3;
@@ -28,25 +28,22 @@ static void ping() {
exit(1);
}
memset(&ping_req, 0, sizeof(struct wsgi_request));
ping_req.uh.modifier1 = UWSGI_MODIFIER_PING;
ping_req.uh.pktsize = 0;
ping_req.uh.modifier2 = 0;
if (write(fd, &ping_req.uh, 4) != 4) {
uh.modifier1 = UWSGI_MODIFIER_PING;
uh.pktsize = 0;
uh.modifier2 = 0;
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
exit(2);
}
ping_req.poll.fd = fd;
ping_req.poll.events = POLLIN;
ping_req.buffer = buf;
if (!uwsgi_parse_packet(&ping_req, uping.ping_timeout)) {
int ret = uwsgi_read_response(fd, &uh, uping.ping_timeout, &buf);
if (ret < 0) {
exit(1);
}
else {
if (ping_req.uh.pktsize > 0) {
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, ping_req.uh.pktsize, buf);
if (uh.pktsize > 0) {
uwsgi_log("[WARNING] node %s message: %.*s\n", uping.ping, uh.pktsize, buf);
exit(2);
}
else {
@@ -94,27 +91,11 @@ int uwsgi_request_ping(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
int uwsgi_ping_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PING:
uwsgi.no_server = 1;
uping.ping = optarg;
return 1;
case LONG_ARGS_PING_TIMEOUT:
uping.ping_timeout = atoi(optarg);
return 1;
}
return 0;
}
struct uwsgi_plugin ping_plugin = {
.name = "ping",
.modifier1 = 100,
.options = uwsgi_ping_options,
.manage_opt = uwsgi_ping_manage_options,
.request = uwsgi_request_ping,
.init = ping_init,
};
+90
View File
@@ -0,0 +1,90 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
int connect_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
// is this a timeout event ?
if (interesting_fd == -1) {
// am i wating for something ?
if (up->fd != -1) {
if (up->cycles > (uint64_t) up->timeout) {
// reset the cycle
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
// avoid duplicated events
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
// ok register a new event
else {
if ((up->cycles % up->freq) == 0) {
up->fd = uwsgi_connect(up->args, -1, 1);
if (up->fd != -1) {
// status = CONNECTING
up->state = 1;
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
return 0;
}
// signal the bad event (if not already bad)
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
}
else if (up->fd != -1) {
// is this event for me ?
if (interesting_fd == up->fd) {
// uselsess here (we have only one state), only to show a good practice
// check the state
if (up->state == 1) {
if (uwsgi_is_bad_connection(up->fd)) {
// signal the bad connection (if needed)
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
if (!up->bad) {
up->bad = 1;
return 1;
}
return 0;
}
// this is a good connection
up->cycles = 0;
close(up->fd);
up->fd = -1;
// state = NOOP
up->state = 0;
if (up->bad) {
up->bad = 0;
return 1;
}
}
}
}
// default action
return 0;
}
int probeconnect_init() {
uwsgi_probe_register(&uwsgi.probes, "connect", connect_prober_callback);
return 0;
}
struct uwsgi_plugin probeconnect_plugin = {
.init = probeconnect_init,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='probeconnect'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['connectprobe']
+132
View File
@@ -0,0 +1,132 @@
#include "../../uwsgi.h"
#include <libpq-fe.h>
extern struct uwsgi_server uwsgi;
int pg_prober_callback(int, struct uwsgi_signal_probe *);
int probepg_init(void);
int pg_prober_callback(int interesting_fd, struct uwsgi_signal_probe *up) {
// is this a timeout event ?
if (interesting_fd == -1) {
// am i wating for something ?
if (up->fd != -1) {
if (up->cycles > (uint64_t) up->timeout) {
// reset the cycle
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
// state = NOOP
up->state = 0;
// avoid duplicated events
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
// ok register a new event
else {
if ((up->cycles % up->freq) == 0) {
up->last_event = event_queue_write();
up->data = (void *) PQconnectStart(up->args);
if (up->data) {
// status = CONNECTING
up->state = PQstatus((PGconn *) up->data);
if (up->state == CONNECTION_BAD)
goto bad;
up->fd = PQsocket((PGconn *) up->data);
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
return 0;
}
bad:
// signal the bad event (if not already bad)
if (!up->bad) {
up->bad = 1;
return 1;
}
}
}
}
else if (up->fd != -1) {
// is this event for me ?
if (interesting_fd == up->fd) {
// check the state
up->state = PQstatus((PGconn *) up->data);
if (up->state == CONNECTION_BAD) {
// signal the bad connection (if needed)
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
up->state = 0;
if (!up->bad) {
up->bad = 1;
return 1;
}
return 0;
}
else if (up->state == CONNECTION_OK) {
up->cycles = 0;
PQfinish((PGconn *) up->data);
up->fd = -1;
// state = NOOP
up->state = 0;
if (up->bad) {
up->bad = 0;
return 1;
}
}
// still wait...
else {
PostgresPollingStatusType wait_type = PQconnectPoll((PGconn *) up->data);
// the connection is good
if (wait_type == PGRES_POLLING_ACTIVE || wait_type == PGRES_POLLING_FAILED || wait_type == PGRES_POLLING_OK) {
if (wait_type == PGRES_POLLING_ACTIVE)
wait_type = PQconnectPoll((PGconn *) up->data);
up->cycles = 0;
up->fd = -1;
// state = NOOP
up->state = 0;
PQfinish((PGconn *) up->data);
if (wait_type == PGRES_POLLING_FAILED) {
if (!up->bad) {
up->bad = 1;
return 1;
}
}
else {
if (up->bad) {
up->bad = 0;
return 1;
}
}
}
else if (wait_type == PGRES_POLLING_READING) {
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
event_queue_add_fd_read(uwsgi.master_queue, up->fd);
up->last_event = event_queue_read();
}
else if (wait_type == PGRES_POLLING_WRITING) {
event_queue_del_fd(uwsgi.master_queue, up->fd, up->last_event);
event_queue_add_fd_write(uwsgi.master_queue, up->fd);
up->last_event = event_queue_write();
}
}
}
}
// default action
return 0;
}
int probepg_init() {
uwsgi_probe_register(&uwsgi.probes, "pg", pg_prober_callback);
return 0;
}
struct uwsgi_plugin probepg_plugin = {
.init = probepg_init,
};
+9
View File
@@ -0,0 +1,9 @@
import os
NAME='probepg'
CFLAGS = os.popen('pg_config --cflags').read().rstrip().split()
CFLAGS.append('-I' + os.popen('pg_config --includedir').read().rstrip())
LDFLAGS = os.popen('pg_config --ldflags').read().rstrip().split()
LIBS = ['-L' + os.popen('pg_config --libdir').read().rstrip(), '-lpq']
GCC_LIST = ['pgprobe']
+22 -15
View File
@@ -11,27 +11,32 @@
struct uwsgi_perl {
int fd;
char *psgibuffer;
// path of the statically loaded main app
char *psgi;
// locallib path
char *locallib;
// perl argv for initialization
char *embedding[3];
PerlInterpreter *main;
pthread_key_t u_interpreter;
PerlInterpreter **interp;
SV *psgi_main;
SV **psgi_func;
CV *stream_responder;
HV *streaming_stash;
HV *input_stash;
HV *error_stash;
// check for Devel::StackTrace
int stacktrace_available;
// this is a pointer to the main list of interpreters (required for signals, rpc....);
PerlInterpreter **main;
// a lock for dynamic apps
pthread_mutex_t lock_loader;
// this fields must be heavy protected in threaded modes
int tmp_current_i;
HV **tmp_streaming_stash;
HV **tmp_input_stash;
HV **tmp_error_stash;
CV **tmp_stream_responder;
};
#define LONG_ARGS_PERL_BASE 17000 + ((5 + 1) * 1000)
#define LONG_ARGS_PSGI LONG_ARGS_PERL_BASE + 1
#define LONG_ARGS_PERL_LOCAL_LIB LONG_ARGS_PERL_BASE + 2
void init_perl_embedded_module(void);
void uwsgi_psgi_app(void);
int psgi_response(struct wsgi_request *, AV*);
@@ -41,3 +46,5 @@ int psgi_response(struct wsgi_request *, AV*);
SV *uwsgi_perl_obj_call(SV *, char *);
int uwsgi_perl_obj_can(SV *, char *, size_t);
int init_psgi_app(struct wsgi_request *, char *, uint16_t, PerlInterpreter **);
PerlInterpreter *uwsgi_perl_new_interpreter(void);
+247 -84
View File
@@ -15,19 +15,23 @@ XS(XS_input_seek) {
XS(XS_error) {
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
psgi_check_args(0);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.error_stash);
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->error)[wsgi_req->async_id]);
XSRETURN(1);
}
XS(XS_input) {
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
psgi_check_args(0);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.input_stash);
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->input)[wsgi_req->async_id]);
XSRETURN(1);
}
@@ -35,6 +39,7 @@ XS(XS_stream)
{
dXSARGS;
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
psgi_check_args(1);
@@ -47,7 +52,7 @@ XS(XS_stream)
while (psgi_response(wsgi_req, response) != UWSGI_OK);
SvREFCNT_dec(response);
ST(0) = sv_bless(newRV(sv_newmortal()), uperl.streaming_stash);
ST(0) = sv_bless(newRV(sv_newmortal()), ((HV **)wi->stream)[wsgi_req->async_id]);
XSRETURN(1);
}
else {
@@ -87,7 +92,7 @@ XS(XS_input_read) {
}
else if (uwsgi.post_buffering > 0) {
fd = -1;
if (wsgi_req->post_cl <= (size_t) uwsgi.post_buffering) {
if (wsgi_req->post_cl > (size_t) uwsgi.post_buffering) {
fd = fileno((FILE *)wsgi_req->async_post);
}
}
@@ -184,6 +189,21 @@ XS(XS_error_print) {
XSRETURN(0);
}
XS(XS_uwsgi_stacktrace) {
dXSARGS;
psgi_check_args(0);
uwsgi_log("*** uWSGI perl stacktrace ***\n");
SV *ret = perl_eval_pv("Devel::StackTrace->new->as_string;", 0);
uwsgi_log("%s", SvPV_nolen(ret));
uwsgi_log("*** end of perl stacktrace ***\n\n");
XSRETURN(0);
}
/* automatically generated */
EXTERN_C void xs_init (pTHX);
@@ -203,18 +223,21 @@ xs_init(pTHX)
newXS("uwsgi::input::read", XS_input_read, "uwsgi::input");
newXS("uwsgi::input::seek", XS_input_seek, "uwsgi::input");
uperl.input_stash = gv_stashpv("uwsgi::input", 0);
uperl.tmp_input_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::input", 0);
newXS("uwsgi::error::new", XS_error, "uwsgi::error");
newXS("uwsgi::error::print", XS_error_print, "uwsgi::print");
uperl.error_stash = gv_stashpv("uwsgi::error", 0);
uperl.tmp_error_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::error", 0);
uperl.stream_responder = newXS("uwsgi::stream", XS_stream, "uwsgi");
uperl.tmp_stream_responder[uperl.tmp_current_i] = newXS("uwsgi::stream", XS_stream, "uwsgi");
newXS("uwsgi::streaming::write", XS_streaming_write, "uwsgi::streaming");
newXS("uwsgi::streaming::close", XS_streaming_close, "uwsgi::streaming");
uperl.streaming_stash = gv_stashpv("uwsgi::streaming", 0);
newXS("uwsgi::stacktrace", XS_uwsgi_stacktrace, "uwsgi");
uperl.tmp_streaming_stash[uperl.tmp_current_i] = gv_stashpv("uwsgi::streaming", 0);
#ifdef UWSGI_EMBEDDED
init_perl_embedded_module();
@@ -224,87 +247,227 @@ xs_init(pTHX)
/* end of automagically generated part */
PerlInterpreter *uwsgi_perl_new_interpreter(void) {
PerlInterpreter *pi = perl_alloc();
if (!pi) {
uwsgi_log("unable to allocate perl interpreter\n");
return NULL;
}
PERL_SET_CONTEXT(pi);
PL_perl_destruct_level = 2;
PL_origalen = 1;
perl_construct(pi);
// over-engeneering
PL_origalen = 1;
return pi;
}
static void uwsgi_perl_free_stashes(void) {
free(uperl.tmp_streaming_stash);
free(uperl.tmp_input_stash);
free(uperl.tmp_error_stash);
free(uperl.tmp_stream_responder);
}
int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, PerlInterpreter **interpreters) {
struct stat st;
int i;
SV **callables;
time_t now = uwsgi_now();
char *app_name = uwsgi_concat2n(app, app_len, "", 0);
// prepare for $0
uperl.embedding[1] = app_name;
int fd = open(app_name, O_RDONLY);
if (fd < 0) {
uwsgi_error_open(app_name);
goto clear2;
}
if (fstat(fd, &st)) {
uwsgi_error("fstat()");
close(fd);
goto clear2;
}
char *buf = uwsgi_calloc(st.st_size+1);
if (read(fd, buf, st.st_size) != st.st_size) {
uwsgi_error("read()");
close(fd);
free(buf);
goto clear2;
}
close(fd);
// the first (default) app, should always be loaded in the main interpreter
if (interpreters == NULL) {
if (uwsgi_apps_cnt) {
interpreters = uwsgi_calloc(sizeof(PerlInterpreter *) * uwsgi.threads);
interpreters[0] = uwsgi_perl_new_interpreter();
if (!interpreters[0]) {
uwsgi_log("unable to create new perl interpreter\n");
free(interpreters);
goto clear2;
}
}
else {
interpreters = uperl.main;
}
}
if (!interpreters) {
goto clear2;
}
callables = uwsgi_calloc(sizeof(SV *) * uwsgi.threads);
uperl.tmp_streaming_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
uperl.tmp_input_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
uperl.tmp_error_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
uperl.tmp_stream_responder = uwsgi_calloc(sizeof(CV *) * uwsgi.threads);
for(i=0;i<uwsgi.threads;i++) {
if (i > 0 && interpreters != uperl.main) {
interpreters[i] = uwsgi_perl_new_interpreter();
if (!interpreters[i]) {
uwsgi_log("unable to create new perl interpreter\n");
// what to do here ? i hope no-one will use threads with dynamic apps...but clear the whole stuff...
free(callables);
uwsgi_perl_free_stashes();
while(i>=0) {
perl_destruct(interpreters[i]);
perl_free(interpreters[i]);
goto clear2;
}
}
}
PERL_SET_CONTEXT(interpreters[i]);
uperl.tmp_current_i = i;
if (uperl.locallib) {
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
uperl.embedding[2] = app_name;
if (perl_parse(interpreters[i], xs_init, 3, uperl.embedding, NULL)) {
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
free(uperl.embedding[1]);
uperl.embedding[1] = app_name;
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
free(uperl.embedding[1]);
uperl.embedding[1] = app_name;
}
else {
if (perl_parse(interpreters[i], xs_init, 2, uperl.embedding, NULL)) {
// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
}
perl_eval_pv("use IO::Handle;", 0);
perl_eval_pv("use IO::File;", 0);
perl_eval_pv("use Devel::StackTrace;", 0);
if (!SvTRUE(ERRSV)) {
uperl.stacktrace_available = 1;
perl_eval_pv("$SIG{__DIE__} = \\&uwsgi::stacktrace;", 0);
}
SV *dollar_zero = get_sv("0", GV_ADD);
sv_setsv(dollar_zero, newSVpv(app, app_len));
callables[i] = perl_eval_pv(uwsgi_concat4("#line 1 ", app_name, "\n", buf), 0);
if (!callables[i]) {
uwsgi_log("unable to find PSGI function entry point.\n");
// what to do here ? i hope no-one will use threads with dynamic apps...
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
PERL_SET_CONTEXT(interpreters[0]);
}
free(buf);
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
free(callables);
uwsgi_perl_free_stashes();
goto clear;
}
int id = uwsgi_apps_cnt;
struct uwsgi_app *wi = NULL;
if (wsgi_req) {
// we need a copy of app_id
wi = uwsgi_add_app(id, 5, uwsgi_concat2n(wsgi_req->appid, wsgi_req->appid_len, "", 0), wsgi_req->appid_len, interpreters, callables);
}
else {
wi = uwsgi_add_app(id, 5, "", 0, interpreters, callables);
}
wi->started_at = now;
wi->startup_time = uwsgi_now() - now;
uwsgi_log("PSGI app %d (%s) loaded in %d seconds at %p (interpreter %p)\n", id, app_name, (int) wi->startup_time, callables[0], interpreters[0]);
free(app_name);
// copy global data to app-specific areas
wi->stream = uperl.tmp_streaming_stash;
wi->input = uperl.tmp_input_stash;
wi->error = uperl.tmp_error_stash;
wi->responder0 = uperl.tmp_stream_responder;
uwsgi_emulate_cow_for_apps(id);
// restore context if required
if (interpreters != uperl.main) {
PERL_SET_CONTEXT(uperl.main[0]);
}
return id;
clear:
if (interpreters != uperl.main) {
for(i=0;i<uwsgi.threads;i++) {
perl_destruct(interpreters[i]);
perl_free(interpreters[i]);
}
free(interpreters);
}
PERL_SET_CONTEXT(uperl.main[0]);
clear2:
free(app_name);
return -1;
}
void uwsgi_psgi_app() {
struct stat stat_psgi;
int id = uwsgi_apps_cnt;
if (uperl.psgi) {
// two-pass loading: parse the script -> eval the script
if (uperl.locallib) {
uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
uperl.embedding[2] = uperl.psgi;
if (perl_parse(uperl.main, xs_init, 3, uperl.embedding, NULL)) {
exit(1);
}
}
else {
uperl.embedding[1] = uperl.psgi;
if (perl_parse(uperl.main, xs_init, 2, uperl.embedding, NULL)) {
exit(1);
}
}
perl_eval_pv("use IO::Handle;", 0);
perl_eval_pv("use IO::File;", 0);
SV *dollar_zero = get_sv("0", GV_ADD);
sv_setsv(dollar_zero, newSVpv(uperl.psgi, 0));
SV *dollar_slash = get_sv("/", GV_ADD);
sv_setsv(dollar_slash, newRV_inc(newSViv(uwsgi.buffer_size)));
uperl.fd = open(uperl.psgi, O_RDONLY);
if (uperl.fd < 0) {
uwsgi_error_open(uperl.psgi);
exit(1);
}
if (fstat(uperl.fd, &stat_psgi)) {
uwsgi_error("fstat()");
exit(1);
}
uperl.psgibuffer = malloc(stat_psgi.st_size + 1);
if (!uperl.psgibuffer) {
uwsgi_error("malloc()");
exit(1);
}
if (read(uperl.fd, uperl.psgibuffer, stat_psgi.st_size) != stat_psgi.st_size) {
uwsgi_error("read()");
exit(1);
}
uperl.psgibuffer[stat_psgi.st_size] = 0;
uperl.psgi_main = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
if (!uperl.psgi_main) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
if (uwsgi.threads < 2) {
free(uperl.psgibuffer);
close(uperl.fd);
}
uwsgi_add_app(id, 5, "", 0);
uwsgi_log("PSGI app %d (%s) loaded at %p\n", id, uperl.psgi, uperl.psgi_main);
//load app in the main interpreter list
init_psgi_app(NULL, uperl.psgi, strlen(uperl.psgi), uperl.main);
}
}
+138 -114
View File
@@ -9,11 +9,11 @@ extern struct uwsgi_perl uperl;
struct uwsgi_perl uperl;
#endif
struct option uwsgi_perl_options[] = {
struct uwsgi_option uwsgi_perl_options[] = {
{"psgi", required_argument, 0, LONG_ARGS_PSGI},
{"perl-local-lib", required_argument, 0, LONG_ARGS_PERL_LOCAL_LIB},
{0, 0, 0, 0},
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
{"perl-local-lib", required_argument, 0, "set perl locallib path", uwsgi_opt_set_str, &uperl.locallib, 0},
{0, 0, 0, 0, 0, 0, 0},
};
@@ -22,8 +22,7 @@ extern struct http_status_codes hsc[];
SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
SV *newobj;
// set current context ?
dTHX;
dSP;
ENTER;
@@ -48,21 +47,21 @@ SV *uwsgi_perl_obj_new(char *class, size_t class_len) {
SV *uwsgi_perl_call_stream(SV *func) {
SV *ret = NULL;
// set current context ?
dTHX;
dSP;
struct wsgi_request *wsgi_req = current_wsgi_req();
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
dSP;
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs( sv_2mortal(newRV((SV*) uperl.stream_responder)));
XPUSHs( sv_2mortal(newRV((SV*) ((SV **)wi->responder0)[wsgi_req->async_id])));
PUTBACK;
call_sv( func, G_SCALAR | G_EVAL);
SPAGAIN;
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
}
else {
ret = SvREFCNT_inc(POPs);
@@ -78,8 +77,7 @@ SV *uwsgi_perl_call_stream(SV *func) {
int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
int ret;
// set current context ? needed for threading
dTHX;
dSP;
ENTER;
@@ -102,12 +100,10 @@ int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
}
SV *uwsgi_perl_obj_call(SV *obj, char *method) {
SV *ret = NULL;
dTHX;
dSP;
ENTER;
@@ -141,7 +137,6 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
AV *ret = NULL;
dTHX;
dSP;
ENTER;
@@ -156,7 +151,7 @@ AV *psgi_call(struct wsgi_request *wsgi_req, SV *psgi_func, SV *env) {
if(SvTRUE(ERRSV)) {
internal_server_error(wsgi_req, "exception raised");
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
uwsgi_log("[uwsgi-perl error] %s\n", SvPV_nolen(ERRSV));
}
else {
ret = (AV *) SvREFCNT_inc(SvRV(POPs));
@@ -284,10 +279,19 @@ int uwsgi_perl_init(){
struct http_status_codes *http_sc;
int argc;
int i;
uperl.embedding[0] = "";
uperl.embedding[1] = "-e";
uperl.embedding[2] = "0";
#ifndef USE_ITHREADS
if (uwsgi.threads > 1) {
uwsgi_log("your Perl environment does not support threads\n");
exit(1);
}
#endif
if (setenv("PLACK_ENV", "uwsgi", 0)) {
uwsgi_error("setenv()");
}
@@ -296,92 +300,102 @@ int uwsgi_perl_init(){
uwsgi_error("setenv()");
}
#ifdef PERL_VERSION_STRING
uwsgi_log("initializing Perl %s environment\n", PERL_VERSION_STRING);
#else
uwsgi_log("initializing Perl environment\n");
#endif
argc = 3;
PERL_SYS_INIT3(&argc, (char ***) &uperl.embedding, &environ);
uperl.main = perl_alloc();
if (!uperl.main) {
uwsgi_log("unable to allocate perl interpreter\n");
uperl.main = uwsgi_calloc(sizeof(PerlInterpreter *) * uwsgi.threads);
uperl.main[0] = uwsgi_perl_new_interpreter();
if (!uperl.main[0]) {
return -1;
}
dTHXa(uperl.main);
PERL_SET_CONTEXT(uperl.main);
for(i=1;i<uwsgi.threads;i++) {
uperl.main[i] = uwsgi_perl_new_interpreter();
if (!uperl.main[i]) {
uwsgi_log("unable to create new perl interpreter for thread %d\n", i+1);
exit(1);
}
}
PL_perl_destruct_level = 2;
PL_origalen = 1;
perl_construct(uperl.main);
PERL_SET_CONTEXT(uperl.main[0]);
// filling http status codes
for (http_sc = hsc; http_sc->message != NULL; http_sc++) {
http_sc->message_size = strlen(http_sc->message);
}
PL_origalen = 1;
#ifdef PERL_VERSION_STRING
uwsgi_log("initialized Perl %s main interpreter at %p\n", PERL_VERSION_STRING, uperl.main[0]);
#else
uwsgi_log("initialized Perl main interpreter at %p\n", uperl.main[0]);
#endif
return 1;
}
#ifdef USE_ITHREADS
void uwsgi_perl_enable_threads() {
if (pthread_key_create(&uperl.u_interpreter, NULL)) {
uwsgi_error("pthread_key_create()");
exit(1);
}
uperl.interp = uwsgi_malloc( sizeof(PerlInterpreter*) * uwsgi.threads );
uperl.interp[0] = uperl.main;
uperl.psgi_func = uwsgi_malloc( sizeof(SV*) * uwsgi.threads );
}
#endif
int uwsgi_perl_request(struct wsgi_request *wsgi_req) {
SV **harakiri;
SV *psgi_func = uperl.psgi_main;
#ifdef UWSGI_ASYNC
if (wsgi_req->async_status == UWSGI_AGAIN) {
return psgi_response(wsgi_req, wsgi_req->async_placeholder);
}
#endif
/* Standard PSGI request */
if (!wsgi_req->uh.pktsize) {
uwsgi_log("Invalid PSGI request. skip.\n");
return -1;
}
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
if (uwsgi.threads > 1) {
psgi_func = uperl.psgi_func[wsgi_req->async_id];
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req->appid, wsgi_req->appid_len, 5);
// if it is -1, try to load a dynamic app
if (wsgi_req->app_id == -1) {
if (wsgi_req->dynamic) {
if (uwsgi.threads > 1) {
pthread_mutex_lock(&uperl.lock_loader);
}
if (wsgi_req->script_len > 0) {
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->script, wsgi_req->script_len, NULL);
}
else if (wsgi_req->file_len > 0) {
wsgi_req->app_id = init_psgi_app(wsgi_req, wsgi_req->file, wsgi_req->file_len, NULL);
}
if (uwsgi.threads > 1) {
pthread_mutex_unlock(&uperl.lock_loader);
}
}
if (wsgi_req->app_id == -1) {
internal_server_error(wsgi_req, "Perl application not found");
// nothing to clear/free
return UWSGI_OK;
}
}
struct uwsgi_app *wi = &uwsgi_apps[wsgi_req->app_id];
wi->requests++;
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
PERL_SET_CONTEXT(((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id]);
}
ENTER;
SAVETMPS;
wsgi_req->async_environ = build_psgi_env(wsgi_req);
if (!wsgi_req->async_environ) goto clear;
wsgi_req->async_result = psgi_call(wsgi_req, psgi_func, wsgi_req->async_environ);
wsgi_req->async_result = psgi_call(wsgi_req, ((SV **)wi->callable)[wsgi_req->async_id], wsgi_req->async_environ);
if (!wsgi_req->async_result) goto clear;
if (SvTYPE((AV *)wsgi_req->async_result) == SVt_PVCV) {
@@ -419,6 +433,11 @@ clear:
FREETMPS;
LEAVE;
// restore main interpreter if needed
if (((PerlInterpreter **)wi->interpreter)[wsgi_req->async_id] != uperl.main[wsgi_req->async_id]) {
PERL_SET_CONTEXT(uperl.main[wsgi_req->async_id]);
}
return UWSGI_OK;
}
@@ -435,56 +454,6 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
}
#ifdef USE_ITHREADS
void uwsgi_perl_init_thread(int core_id) {
if (core_id > 0) {
uperl.interp[core_id] = perl_clone(uperl.main, CLONEf_KEEP_PTR_TABLE);
if (!uperl.interp[core_id]) {
uwsgi_log("unable to create new perl interpreter\n");
exit(1);
}
}
dTHXa(uperl.interp[core_id]);
PERL_SET_CONTEXT(uperl.interp[core_id]);
pthread_setspecific(uperl.u_interpreter, uperl.interp[core_id]);
uperl.psgi_func[0] = uperl.psgi_main;
if (core_id > 0) {
uperl.psgi_func[core_id] = perl_eval_pv(uwsgi_concat4("#line 1 ", uperl.psgi, "\n", uperl.psgibuffer), 0);
if (!uperl.psgi_func[core_id]) {
uwsgi_log("unable to find PSGI function entry point.\n");
exit(1);
}
if(SvTRUE(ERRSV)) {
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
exit(1);
}
}
}
#endif
int uwsgi_perl_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PSGI:
uperl.psgi = optarg;
return 1;
case LONG_ARGS_PERL_LOCAL_LIB:
uperl.locallib = optarg;
return 1;
}
return 0;
}
int uwsgi_perl_magic(char *mountpoint, char *lazy) {
if (!strcmp(lazy+strlen(lazy)-5, ".psgi")) {
@@ -500,6 +469,61 @@ int uwsgi_perl_magic(char *mountpoint, char *lazy) {
}
// taken from Torsten Foertsch AfterFork.xs
void uwsgi_perl_post_fork() {
/*
GV *tmpgv;
PL_ppid = (IV)getppid();
hv_clear(PL_pidstatus);
tmpgv = gv_fetchpv("$", TRUE, SVt_PV);
if (tmpgv) {
SvREADONLY_off(GvSV(tmpgv));
sv_setiv(GvSV(tmpgv), (IV)getpid());
SvREADONLY_on(GvSV(tmpgv));
}
*/
}
int uwsgi_perl_mount_app(char *mountpoint, char *app, int regexp) {
if (uwsgi_endswith(app, ".pl") || uwsgi_endswith(app, ".psgi")) {
uwsgi.wsgi_req->appid = mountpoint;
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
return init_psgi_app(uwsgi.wsgi_req, app, strlen(app), NULL);
}
return -1;
}
void uwsgi_perl_init_thread(int core_id) {
#ifdef USE_ITHREADS
PERL_SET_CONTEXT(uperl.main[core_id]);
#endif
}
void uwsgi_perl_pthread_prepare(void) {
pthread_mutex_lock(&uperl.lock_loader);
}
void uwsgi_perl_pthread_parent(void) {
pthread_mutex_unlock(&uperl.lock_loader);
}
void uwsgi_perl_pthread_child(void) {
pthread_mutex_init(&uperl.lock_loader, NULL);
}
void uwsgi_perl_enable_threads(void) {
#ifdef USE_ITHREADS
pthread_mutex_init(&uperl.lock_loader, NULL);
pthread_atfork(uwsgi_perl_pthread_prepare, uwsgi_perl_pthread_parent, uwsgi_perl_pthread_child);
#endif
}
struct uwsgi_plugin psgi_plugin = {
@@ -507,16 +531,16 @@ struct uwsgi_plugin psgi_plugin = {
.modifier1 = 5,
.init = uwsgi_perl_init,
.options = uwsgi_perl_options,
.init_apps = uwsgi_psgi_app,
//.magic = uwsgi_perl_magic,
//.help = uwsgi_perl_help,
#ifdef USE_ITHREADS
.enable_threads = uwsgi_perl_enable_threads,
.mount_app = uwsgi_perl_mount_app,
.init_thread = uwsgi_perl_init_thread,
#endif
.manage_opt = uwsgi_perl_manage_options,
.post_fork = uwsgi_perl_post_fork,
.request = uwsgi_perl_request,
.after_request = uwsgi_perl_after_request,
.enable_threads = uwsgi_perl_enable_threads,
.magic = uwsgi_perl_magic,
};
+1
View File
@@ -147,6 +147,7 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
wsgi_req->sendfile_fd = SvIV(fn);
SvREFCNT_dec(fn);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
// no need to close here as perl GC will do the close()
return UWSGI_OK;
}
+14 -6
View File
@@ -96,6 +96,8 @@ XS(XS_cache_set) {
char *key, *val;
STRLEN keylen;
STRLEN vallen;
if (uwsgi.cache_max_items == 0) goto clear;
psgi_check_args(2);
@@ -104,6 +106,7 @@ XS(XS_cache_set) {
uwsgi_cache_set(key, (uint16_t) keylen, val, (uint64_t) vallen, 0, 0);
clear:
XSRETURN_UNDEF;
}
@@ -113,6 +116,8 @@ XS(XS_cache_get) {
char *key, *val;
STRLEN keylen;
uint64_t vallen;
if (uwsgi.cache_max_items == 0) goto clear;
psgi_check_args(1);
@@ -121,6 +126,7 @@ XS(XS_cache_get) {
val = uwsgi_cache_get(key, (uint16_t) keylen, &vallen);
if (!val)
clear:
XSRETURN_UNDEF;
ST(0) = newSVpv(val, vallen);
@@ -155,26 +161,28 @@ XS(XS_call) {
dXSARGS;
char buffer[0xffff];
char *func;
uint16_t size = 0;
int i;
char *argv[0xff];
char *argv[256];
uint16_t argvs[256];
STRLEN arg_len;
psgi_check_args(1);
func = SvPV_nolen(ST(0));
for(i=0;i<(items-1);i++) {
argv[i] = SvPV_nolen(ST(i+1));
argv[i] = SvPV(ST(i+1), arg_len);
argvs[i] = arg_len;
}
size = uwsgi_rpc(func, items-1, argv, buffer);
char *response = uwsgi_do_rpc(NULL, func, items-1, argv, argvs, &size);
if (size > 0) {
ST(0) = newSVpv(buffer, size);
ST(0) = newSVpv(response, size);
sv_2mortal(ST(0));
free(response);
XSRETURN(1);
}
+1 -1
View File
@@ -342,12 +342,12 @@ int uwsgi_response_subhandler_pump(struct wsgi_request *wsgi_req) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
#endif
}
else {
uwsgi_log("invalid Pump response.\n");
goto clear;
}
#endif
}
+71 -39
View File
@@ -80,14 +80,13 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
int id = uwsgi_apps_cnt;
int multiapp = 0;
#ifdef UWSGI_ASYNC
int i;
#endif
char *mountpoint;
struct uwsgi_app *wi;
time_t now = uwsgi_now();
mountpoint = uwsgi_strncopy(wsgi_req->appid, wsgi_req->appid_len);
@@ -320,9 +319,9 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
// add start_response on WSGI app
Py_INCREF((PyObject *)up.wsgi_spitout);
wi->wsgi_args = PyTuple_New(wi->argc);
wi->args = PyTuple_New(wi->argc);
if (app_type == PYTHON_APP_TYPE_WSGI) {
if (PyTuple_SetItem(wi->wsgi_args, 1, up.wsgi_spitout)) {
if (PyTuple_SetItem(wi->args, 1, up.wsgi_spitout)) {
uwsgi_log("unable to set start_response in args tuple\n");
exit(1);
}
@@ -370,24 +369,28 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
PyThreadState_Swap(up.main_thread);
}
if (app_type == PYTHON_APP_TYPE_WSGI) {
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
else if (app_type == PYTHON_APP_TYPE_WEB3) {
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid());
}
const char *default_app = "";
if ((wsgi_req->appid_len == 0 || (wsgi_req->appid_len = 1 && wsgi_req->appid[0] == '/')) && uwsgi.default_app == -1) {
uwsgi_rawlog(" (default app)");
default_app = " (default app)" ;
uwsgi.default_app = id;
}
uwsgi_apps_cnt++;
wi->started_at = now;
wi->startup_time = uwsgi_now() - now;
uwsgi_rawlog("\n");
if (app_type == PYTHON_APP_TYPE_WSGI) {
uwsgi_log( "WSGI app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
}
else if (app_type == PYTHON_APP_TYPE_WEB3) {
uwsgi_log( "Web3 app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
uwsgi_log( "Pump app %d (mountpoint='%.*s') ready in %d seconds on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, (int) wi->startup_time, wi->interpreter, (int) getpid(), default_app);
}
uwsgi_apps_cnt++;
if (multiapp > 1) {
for(i=1;i<multiapp;i++) {
@@ -415,13 +418,8 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
}
}
// check if we need to emulate fork() COW
if (uwsgi.mywid == 0) {
for(i=1;i<=uwsgi.numproc;i++) {
memcpy(&uwsgi.workers[i].apps[id], &uwsgi.workers[0].apps[id], sizeof(struct uwsgi_app));
uwsgi.workers[i].apps_cnt = uwsgi_apps_cnt;
}
}
// emulate COW
uwsgi_emulate_cow_for_apps(id);
return id;
@@ -540,6 +538,7 @@ PyObject *uwsgi_mount_loader(void *arg1) {
if ( !strcmp(what+strlen(what)-3, ".py") || !strcmp(what+strlen(what)-5, ".wsgi")) {
callable = uwsgi_file_loader((void *)what);
if (!callable) exit(UWSGI_FAILED_APP_CODE);
}
else if (!strcmp(what+strlen(what)-4, ".ini")) {
callable = uwsgi_paste_loader((void *)what);
@@ -606,30 +605,44 @@ PyObject *uwsgi_file_loader(void *arg1) {
char *callable = up.callable;
if (!callable) callable = "application";
wsgi_file_module = uwsgi_pyimport_by_filename(uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename)), filename);
char *py_filename = uwsgi_concat2("uwsgi_file_", uwsgi_pythonize(filename));
wsgi_file_module = uwsgi_pyimport_by_filename(py_filename, filename);
if (!wsgi_file_module) {
PyErr_Print();
exit(1);
free(py_filename);
return NULL;
}
wsgi_file_dict = PyModule_GetDict(wsgi_file_module);
if (!wsgi_file_dict) {
PyErr_Print();
exit(1);
Py_DECREF(wsgi_file_module);
free(py_filename);
return NULL;
}
wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, callable);
if (!wsgi_file_callable) {
PyErr_Print();
Py_DECREF(wsgi_file_dict);
Py_DECREF(wsgi_file_module);
free(py_filename);
uwsgi_log( "unable to find \"application\" callable in file %s\n", filename);
exit(1);
return NULL;
}
if (!PyFunction_Check(wsgi_file_callable) && !PyCallable_Check(wsgi_file_callable)) {
uwsgi_log( "\"application\" must be a callable object in file %s\n", filename);
exit(1);
Py_DECREF(wsgi_file_callable);
Py_DECREF(wsgi_file_dict);
Py_DECREF(wsgi_file_module);
free(py_filename);
return NULL;
}
free(py_filename);
return wsgi_file_callable;
}
@@ -641,39 +654,58 @@ PyObject *uwsgi_paste_loader(void *arg1) {
PyObject *paste_arg, *paste_app;
uwsgi_log( "Loading paste environment: %s\n", paste);
if (up.paste_logger) {
PyObject *paste_logger_dict = get_uwsgi_pydict("paste.script.util.logging_config");
if (paste_logger_dict) {
PyObject *paste_logger_fileConfig = PyDict_GetItemString(paste_logger_dict, "fileConfig");
if (paste_logger_fileConfig) {
PyObject *paste_logger_arg = PyTuple_New(1);
if (!paste_logger_arg) {
PyErr_Print();
exit(UWSGI_FAILED_APP_CODE);
}
PyTuple_SetItem(paste_logger_arg, 0, PyString_FromString(paste+7));
if (python_call(paste_logger_fileConfig, paste_logger_arg, 0, NULL)) {
PyErr_Print();
}
}
}
}
paste_module = PyImport_ImportModule("paste.deploy");
if (!paste_module) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
paste_dict = PyModule_GetDict(paste_module);
if (!paste_dict) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
paste_loadapp = PyDict_GetItemString(paste_dict, "loadapp");
if (!paste_loadapp) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
paste_arg = PyTuple_New(1);
if (!paste_arg) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
if (PyTuple_SetItem(paste_arg, 0, PyString_FromString(paste))) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
paste_app = PyEval_CallObject(paste_loadapp, paste_arg);
if (!paste_app) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
@@ -695,7 +727,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
if (!wsgi_eval_node) {
PyErr_Print();
uwsgi_log( "failed to parse <eval> code\n");
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
wsgi_compiled_node = (PyObject *) PyNode_Compile(wsgi_eval_node, "uwsgi_eval_config");
@@ -703,14 +735,14 @@ PyObject *uwsgi_eval_loader(void *arg1) {
if (!wsgi_compiled_node) {
PyErr_Print();
uwsgi_log( "failed to compile eval code\n");
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
wsgi_eval_module = PyImport_ExecCodeModule("uwsgi_eval_config", wsgi_compiled_node);
if (!wsgi_eval_module) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
@@ -719,7 +751,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
up.loader_dict = PyModule_GetDict(wsgi_eval_module);
if (!up.loader_dict) {
PyErr_Print();
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
@@ -734,7 +766,7 @@ PyObject *uwsgi_eval_loader(void *arg1) {
if (wsgi_eval_callable) {
if (!PyFunction_Check(wsgi_eval_callable) && !PyCallable_Check(wsgi_eval_callable)) {
uwsgi_log( "you must define a callable object in your code\n");
exit(1);
exit(UWSGI_FAILED_APP_CODE);
}
}
+330 -277
View File
@@ -9,76 +9,119 @@ extern struct http_status_codes hsc[];
extern PyTypeObject uwsgi_InputType;
struct option uwsgi_python_options[] = {
{"wsgi-file", required_argument, 0, LONG_ARGS_WSGI_FILE},
{"file", required_argument, 0, LONG_ARGS_FILE_CONFIG},
{"eval", required_argument, 0, LONG_ARGS_EVAL_CONFIG},
{"module", required_argument, 0, 'w'},
{"wsgi", required_argument, 0, 'w'},
{"callable", required_argument, 0, LONG_ARGS_CALLABLE},
{"test", required_argument, 0, 'J'},
{"home", required_argument, 0, 'H'},
{"virtualenv", required_argument, 0, 'H'},
{"venv", required_argument, 0, 'H'},
{"pyhome", required_argument, 0, 'H'},
{"pythonpath", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"python-path", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"pymodule-alias", required_argument, 0, LONG_ARGS_PYMODULE_ALIAS},
{"post-pymodule-alias", required_argument, 0, LONG_ARGS_POST_PYMODULE_ALIAS},
{"import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"pyimport", required_argument, 0, LONG_ARGS_PYIMPORT},
{"py-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"python-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"spooler-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-pyimport", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-py-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"spooler-python-import", required_argument, 0, LONG_ARGS_SPOOLER_PYIMPORT},
{"pp", required_argument, 0, LONG_ARGS_PYTHONPATH},
{"pyargv", required_argument, 0, LONG_ARGS_PYARGV},
{"optimize", required_argument, 0, 'O'},
{"paste", required_argument, 0, LONG_ARGS_PASTE},
{"web3", required_argument, 0, LONG_ARGS_WEB3},
{"pump", required_argument, 0, LONG_ARGS_PUMP},
{"wsgi-lite", required_argument, 0, LONG_ARGS_WSGI_LITE},
void uwsgi_opt_pythonpath(char *opt, char *value, void *foobar) {
int i;
glob_t g;
if (glob(value, GLOB_MARK, NULL, &g)) {
uwsgi_string_new_list(&up.python_path, value);
}
else {
for (i = 0; i < (int) g.gl_pathc; i++) {
uwsgi_string_new_list(&up.python_path, g.gl_pathv[i]);
}
}
}
void uwsgi_opt_pyshell(char *opt, char *value, void *foobar) {
uwsgi.honour_stdin = 1;
up.pyshell = 1;
if (!strcmp("pyshell-oneshot", opt)) {
up.pyshell_oneshot = 1;
}
}
void uwsgi_opt_pyrun(char *opt, char *value, void *foobar) {
uwsgi.honour_stdin = 1;
uwsgi.command_mode = 1;
up.pyrun = value;
}
#ifdef UWSGI_INI
{"ini-paste", required_argument, 0, LONG_ARGS_INI_PASTE},
void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {
uwsgi_opt_load_ini(opt, value, NULL);
if (value[0] != '/') {
up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", value);
}
else {
up.paste = uwsgi_concat2("config:", value);
}
if (!strcmp("ini-paste-logged", opt)) {
up.paste_logger = 1;
}
}
#endif
{"catch-exceptions", no_argument, &up.catch_exceptions, 1},
{"ignore-script-name", no_argument, &up.ignore_script_name, 1},
{"pep3333-input", no_argument, &up.pep3333_input, 1},
{"reload-os-env", no_argument, &up.reload_os_env, 1},
struct uwsgi_option uwsgi_python_options[] = {
{"wsgi-file", required_argument, 0, "load .wsgi file", uwsgi_opt_set_str, &up.file_config, 0},
{"file", required_argument, 0, "load .wsgi file", uwsgi_opt_set_str, &up.file_config, 0},
{"eval", required_argument, 0, "eval python code", uwsgi_opt_set_str, &up.eval, 0},
{"module", required_argument,'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0},
{"wsgi", required_argument, 'w', "load a WSGI module", uwsgi_opt_set_str, &up.wsgi_config, 0},
{"callable", required_argument, 0, "set default WSGI callable name", uwsgi_opt_set_str, &up.callable, 0},
{"test", required_argument, 'J', "test a mdule import", uwsgi_opt_set_str, &up.test_module, 0},
{"home", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
{"virtualenv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
{"venv", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
{"pyhome", required_argument, 'H', "set PYTHONHOME/virtualenv", uwsgi_opt_set_str, &up.home, 0},
{"pythonpath", required_argument, 0, "add directory (or glob) to pythonpath", uwsgi_opt_pythonpath, NULL, 0},
{"python-path", required_argument, 0, "add directory (or glob) to pythonpath", uwsgi_opt_pythonpath, NULL, 0},
{"pp", required_argument, 0, "add directory (or glob) to pythonpath", uwsgi_opt_pythonpath, NULL, 0},
{"pymodule-alias", required_argument, 0, "add a python alias module", uwsgi_opt_add_string_list, &up.pymodule_alias, 0},
{"post-pymodule-alias", required_argument, 0, "add a python module alias after uwsgi module initialization", uwsgi_opt_add_string_list, &up.post_pymodule_alias, 0},
{"import", required_argument, 0, "import a python module", uwsgi_opt_add_string_list, &up.import_list, 0},
{"pyimport", required_argument, 0, "import a python module", uwsgi_opt_add_string_list, &up.import_list, 0},
{"py-import", required_argument, 0, "import a python module", uwsgi_opt_add_string_list, &up.import_list, 0},
{"python-import", required_argument, 0, "import a python module", uwsgi_opt_add_string_list, &up.import_list, 0},
{"shared-import", required_argument, 0, "import a python module in all of the processes", uwsgi_opt_add_string_list, &up.shared_import_list, 0},
{"shared-pyimport", required_argument, 0, "import a python module in all of the processes", uwsgi_opt_add_string_list, &up.shared_import_list, 0},
{"shared-py-import", required_argument, 0, "import a python module in all of the processes", uwsgi_opt_add_string_list, &up.shared_import_list, 0},
{"shared-python-import", required_argument, 0, "import a python module in all of the processes", uwsgi_opt_add_string_list, &up.shared_import_list, 0},
{"spooler-import", required_argument, 0, "import a python module in the spooler", uwsgi_opt_add_string_list, &up.spooler_import_list},
{"spooler-pyimport", required_argument, 0, "import a python module in the spooler", uwsgi_opt_add_string_list, &up.spooler_import_list},
{"spooler-py-import", required_argument, 0, "import a python module in the spooler", uwsgi_opt_add_string_list, &up.spooler_import_list},
{"spooler-python-import", required_argument, 0, "import a python module in the spooler", uwsgi_opt_add_string_list, &up.spooler_import_list},
{"pyargv", required_argument, 0, "manually set sys.argv", uwsgi_opt_set_str, &up.argv, 0},
{"optimize", required_argument, 'O', "set python optimization level", uwsgi_opt_set_int, &up.optimize, 0},
{"paste", required_argument, 0, "load a paste.deploy config file", uwsgi_opt_set_str, &up.paste, 0},
{"paste-logger", no_argument, 0, "enable paste fileConfig logger", uwsgi_opt_true, &up.paste_logger, 0},
{"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
{"catch-exceptions", no_argument, 0, "report exception has http output (discouraged)", uwsgi_opt_true, &up.catch_exceptions, 0},
{"ignore-script-name", no_argument, 0, "ignore SCRIPT_NAME", uwsgi_opt_true, &up.ignore_script_name, 0},
{"reload-os-env", no_argument, 0, "force reload of os.environ at each request", uwsgi_opt_true, &up.reload_os_env, 0},
#ifndef UWSGI_PYPY
{"no-site", no_argument, &Py_NoSiteFlag, 1},
{"no-site", no_argument, 0, "do not import site module", uwsgi_opt_true, &Py_NoSiteFlag, 0},
#endif
{"pyshell", no_argument, 0, LONG_ARGS_PYSHELL},
{"python", required_argument, 0, LONG_ARGS_PYTHON_RUN},
{"py", required_argument, 0, LONG_ARGS_PYTHON_RUN},
{"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},
{0, 0, 0, 0},
};
{"python", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
{"py", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
{"pyrun", required_argument, 0, "run a python script in the uWSGI environment", uwsgi_opt_pyrun, NULL, 0},
struct uwsgi_help_item uwsgi_python_help[] = {
{"module <module>" ,"name of python config module"},
{"optimize <n>", "set python optimization level to <n>"},
{"home <path>", "set python home/virtualenv"},
{"pyhome <path>", "set python home/virtualenv"},
{"virtualenv <path>", "set python home/virtualenv"},
{"venv <path>", "set python home/virtualenv"},
{"callable <callable>", "set the callable (default 'application')"},
{"paste <config:/egg:>", "load applications using paste.deploy.loadapp()"},
{"pythonpath <dir>", "add <dir> to PYTHONPATH"},
{"python-path <dir>", "add <dir> to PYTHONPATH"},
{"pp <dir>", "add <dir> to PYTHONPATH"},
{"pyargv <args>", "assign args to python sys.argv"},
{"wsgi-file <file>", "load the <file> wsgi file"},
{"file <file>", "use python file instead of python module for configuration"},
{"eval <code>", "evaluate code for app configuration"},
{"ini-paste <inifile>", "path of ini config file that contains paste configuration"},
{"pyshell", "run a python interactive shell in the uwsgi environment (steals a worker)"},
{ 0, 0},
{0, 0, 0, 0, 0, 0, 0},
};
/* this routine will be called after each fork to reinitialize the various locks */
@@ -94,11 +137,6 @@ void uwsgi_python_pthread_child(void) {
pthread_mutex_init(&up.lock_pyloaders, NULL);
}
// fake method
PyMethodDef null_methods[] = {
{NULL, NULL},
};
PyMethodDef uwsgi_spit_method[] = { {"uwsgi_spit", py_uwsgi_spit, METH_VARARGS, ""} };
PyMethodDef uwsgi_write_method[] = { {"uwsgi_write", py_uwsgi_write, METH_VARARGS, ""} };
@@ -106,9 +144,9 @@ int uwsgi_python_init() {
#ifndef UWSGI_PYPY
char *pyversion = strchr(Py_GetVersion(), '\n');
uwsgi_log("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
#else
uwsgi_log("PyPy version: %s\n", PYPY_VERSION);
uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
#endif
#ifndef UWSGI_PYPY
@@ -160,7 +198,7 @@ int uwsgi_python_init() {
up.reset_ts = simple_reset_ts;
uwsgi_log("Python main interpreter initialized at %p\n", up.main_thread);
uwsgi_log_initial("Python main interpreter initialized at %p\n", up.main_thread);
return 1;
@@ -191,13 +229,60 @@ void uwsgi_python_reset_random_seed() {
#endif
}
void uwsgi_python_atexit() {
// if hijacked do not run atexit hooks
if (uwsgi.workers[uwsgi.mywid].hijacked)
return;
// if busy do not run atexit hooks
if (uwsgi.workers[uwsgi.mywid].busy)
return;
#ifdef UWSGI_ASYNC
// managing atexit in async mode is a real pain...skip it for now
if (uwsgi.async > 1)
return;
#endif
// this time we use this higher level function
// as this code can be executed in a signal handler
if (!Py_IsInitialized()) {
return;
}
if (uwsgi.has_threads)
PyGILState_Ensure();
// no need to worry about freeing memory
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
if (uwsgi_dict) {
PyObject *ae = PyDict_GetItemString(uwsgi_dict, "atexit");
if (ae) {
python_call(ae, PyTuple_New(0), 0, NULL);
}
}
// this part is a 1:1 copy of mod_wsgi 3.x
// it is required to fix some atexit bug with python 3
// and to shutdown useless threads complaints
PyObject *module = PyImport_ImportModule("atexit");
Py_XDECREF(module);
if (uwsgi.threads > 1) {
if (!PyImport_AddModule("dummy_threading"))
PyErr_Clear();
}
Py_Finalize();
}
void uwsgi_python_post_fork() {
#ifdef UWSGI_SPOOLER
if (uwsgi.shared->spooler_pid > 0) {
if (uwsgi.shared->spooler_pid == getpid()) {
UWSGI_GET_GIL
}
if (uwsgi.i_am_a_spooler) {
UWSGI_GET_GIL
}
#endif
@@ -253,7 +338,6 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
if (!pyfile) {
uwsgi_error_open(real_filename);
free(real_filename);
fclose(pyfile);
return NULL;
}
}
@@ -317,7 +401,6 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
void init_uwsgi_vars() {
int i;
PyObject *pysys, *pysys_dict, *pypath;
PyObject *modules = PyImport_GetModuleDict();
@@ -361,9 +444,10 @@ void init_uwsgi_vars() {
uppp = uppp->next;
}
for (i = 0; i < up.pymodule_alias_cnt; i++) {
struct uwsgi_string_list *uppma = up.pymodule_alias;
while(uppma) {
// split key=value
char *value = strchr(up.pymodule_alias[i], '=');
char *value = strchr(uppma->value, '=');
if (!value) {
uwsgi_log("invalid pymodule-alias syntax\n");
continue;
@@ -377,39 +461,43 @@ void init_uwsgi_vars() {
exit(1);
}
PyDict_SetItemString(modules, up.pymodule_alias[i], tmp_module);
PyDict_SetItemString(modules, uppma->value, tmp_module);
}
else {
// this is a filepath that need to be mapped
tmp_module = uwsgi_pyimport_by_filename(up.pymodule_alias[i], value + 1);
tmp_module = uwsgi_pyimport_by_filename(uppma->value, value + 1);
if (!tmp_module) {
PyErr_Print();
exit(1);
}
}
uwsgi_log("mapped virtual pymodule \"%s\" to real pymodule \"%s\"\n", up.pymodule_alias[i], value + 1);
uwsgi_log("mapped virtual pymodule \"%s\" to real pymodule \"%s\"\n", uppma->value, value + 1);
// reset original value
value[0] = '=';
uppma = uppma->next;
}
}
PyDoc_STRVAR(uwsgi_py_doc, "uWSGI api module.");
#ifdef PYTHREE
static PyModuleDef uwsgi_module3 = {
PyModuleDef_HEAD_INIT,
"uwsgi",
NULL,
uwsgi_py_doc,
-1,
null_methods,
NULL,
};
PyObject *init_uwsgi3(void) {
return PyModule_Create(&uwsgi_module3);
}
#endif
#ifdef UWSGI_EMBEDDED
void init_uwsgi_embedded_module() {
PyObject *new_uwsgi_module, *zero;
@@ -426,18 +514,19 @@ void init_uwsgi_embedded_module() {
}
#ifdef PYTHREE
PyImport_AppendInittab("uwsgi", init_uwsgi3);
new_uwsgi_module = PyImport_AddModule("uwsgi");
#else
new_uwsgi_module = Py_InitModule("uwsgi", null_methods);
new_uwsgi_module = Py_InitModule3("uwsgi", NULL, uwsgi_py_doc);
#endif
if (new_uwsgi_module == NULL) {
uwsgi_log("could not initialize the uwsgi python module\n");
exit(1);
}
Py_INCREF((PyObject *) &uwsgi_InputType);
up.embedded_dict = PyModule_GetDict(new_uwsgi_module);
@@ -468,6 +557,7 @@ void init_uwsgi_embedded_module() {
}
if (PyDict_SetItemString(up.embedded_dict, "hostname", PyString_FromStringAndSize(uwsgi.hostname, uwsgi.hostname_len))) {
PyErr_Print();
exit(1);
@@ -487,6 +577,31 @@ void init_uwsgi_embedded_module() {
}
}
#ifdef UWSGI_SPOOLER
if (uwsgi.spoolers) {
int sc = 0;
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while(uspool) { sc++; uspool = uspool->next;}
PyObject *py_spooler_tuple = PyTuple_New(sc);
uspool = uwsgi.spoolers;
sc = 0;
while(uspool) {
PyTuple_SetItem(py_spooler_tuple, sc, PyString_FromString(uspool->dir));
sc++;
uspool = uspool->next;
}
if (PyDict_SetItemString(up.embedded_dict, "spoolers", py_spooler_tuple)) {
PyErr_Print();
exit(1);
}
}
#endif
if (PyDict_SetItemString(up.embedded_dict, "SPOOL_RETRY", PyInt_FromLong(-1))) {
PyErr_Print();
@@ -606,11 +721,6 @@ void init_uwsgi_embedded_module() {
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "fastfuncs", PyList_New(256))) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "applications", Py_None)) {
PyErr_Print();
@@ -641,16 +751,10 @@ void init_uwsgi_embedded_module() {
exit(1);
}
up.fastfuncslist = PyDict_GetItemString(up.embedded_dict, "fastfuncs");
if (!up.fastfuncslist) {
PyErr_Print();
exit(1);
}
init_uwsgi_module_advanced(new_uwsgi_module);
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir != NULL) {
if (uwsgi.spoolers) {
init_uwsgi_module_spooler(new_uwsgi_module);
}
#endif
@@ -711,111 +815,19 @@ int uwsgi_python_magic(char *mountpoint, char *lazy) {
}
int uwsgi_python_manage_options(int i, char *optarg) {
glob_t g;
int j;
switch (i) {
case 'w':
up.wsgi_config = optarg;
return 1;
case LONG_ARGS_WSGI_FILE:
case LONG_ARGS_FILE_CONFIG:
up.file_config = optarg;
return 1;
case LONG_ARGS_EVAL_CONFIG:
up.eval = optarg;
return 1;
case LONG_ARGS_PYMODULE_ALIAS:
if (up.pymodule_alias_cnt < MAX_PYMODULE_ALIAS) {
up.pymodule_alias[up.pymodule_alias_cnt] = optarg;
up.pymodule_alias_cnt++;
}
else {
uwsgi_log("you can specify at most %d --pymodule-alias options\n", MAX_PYMODULE_ALIAS);
}
return 1;
case LONG_ARGS_PYSHELL:
uwsgi.honour_stdin = 1;
up.pyshell = 1;
return 1;
case LONG_ARGS_PYIMPORT:
uwsgi_string_new_list(&up.import_list, optarg);
return 1;
case LONG_ARGS_SPOOLER_PYIMPORT:
uwsgi_string_new_list(&up.spooler_import_list, optarg);
return 1;
case LONG_ARGS_POST_PYMODULE_ALIAS:
uwsgi_string_new_list(&up.post_pymodule_alias, optarg);
return 1;
case LONG_ARGS_PYTHONPATH:
if (glob(optarg, GLOB_MARK, NULL, &g)) {
uwsgi_string_new_list(&up.python_path, optarg);
}
else {
for (j = 0; j < (int) g.gl_pathc; j++) {
uwsgi_string_new_list(&up.python_path, g.gl_pathv[j]);
}
}
return 1;
case LONG_ARGS_PYARGV:
up.argv = optarg;
return 1;
case 'J':
up.test_module = optarg;
return 1;
case 'H':
up.home = optarg;
return 1;
case 'O':
up.optimize = atoi(optarg);
return 1;
case LONG_ARGS_CALLABLE:
up.callable = optarg;
return 1;
#ifdef UWSGI_INI
case LONG_ARGS_INI_PASTE:
uwsgi_string_new_list(&uwsgi.ini,optarg);
if (optarg[0] != '/') {
up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", optarg);
}
else {
up.paste = uwsgi_concat2("config:", optarg);
}
return 1;
#endif
case LONG_ARGS_WEB3:
up.web3 = optarg;
return 1;
case LONG_ARGS_PUMP:
up.pump = optarg;
return 1;
case LONG_ARGS_WSGI_LITE:
up.wsgi_lite = optarg;
return 1;
case LONG_ARGS_PASTE:
up.paste = optarg;
return 1;
}
return 0;
}
int uwsgi_python_mount_app(char *mountpoint, char *app, int regexp) {
int id;
uwsgi.wsgi_req->appid = mountpoint;
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
if (uwsgi.single_interpreter) {
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
if (strchr(app, ':') || uwsgi_endswith(app, ".py") || uwsgi_endswith(app, ".wsgi")) {
uwsgi.wsgi_req->appid = mountpoint;
uwsgi.wsgi_req->appid_len = strlen(mountpoint);
if (uwsgi.single_interpreter) {
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, up.main_thread, PYTHON_APP_TYPE_WSGI);
}
else {
id = init_uwsgi_app(LOADER_MOUNT, app, uwsgi.wsgi_req, NULL, PYTHON_APP_TYPE_WSGI);
}
#ifdef UWSGI_PCRE
int i;
@@ -831,7 +843,9 @@ int uwsgi_python_mount_app(char *mountpoint, char *app, int regexp) {
}
#endif
return id;
return id;
}
return -1;
}
@@ -893,17 +907,8 @@ void uwsgi_python_spooler_init(void) {
}
void uwsgi_python_init_apps() {
struct http_status_codes *http_sc;
if (uwsgi.async > 1) {
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
#ifndef UWSGI_PYPY
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
#endif
}
// this hook will be executed by master (or worker1 when master is not requested, so COW is in place)
void uwsgi_python_preinit_apps() {
init_pyargv();
@@ -913,7 +918,6 @@ void uwsgi_python_init_apps() {
#endif
#endif
#ifdef __linux__
#ifndef UWSGI_PYPY
#ifdef UWSGI_EMBEDDED
@@ -931,6 +935,34 @@ void uwsgi_python_init_apps() {
init_uwsgi_vars();
// load shared imports
struct uwsgi_string_list *upli = up.shared_import_list;
while(upli) {
if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) {
uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value);
}
else {
if (PyImport_ImportModule(upli->value) == NULL) {
PyErr_Print();
}
}
upli = upli->next;
}
}
void uwsgi_python_init_apps() {
struct http_status_codes *http_sc;
// prepare for stack suspend/resume
if (uwsgi.async > 1) {
up.current_recursion_depth = uwsgi_malloc(sizeof(int)*uwsgi.async);
#ifndef UWSGI_PYPY
up.current_frame = uwsgi_malloc(sizeof(struct _frame)*uwsgi.async);
#endif
}
// setup app loaders
#ifdef UWSGI_MINTERPRETERS
up.loaders[LOADER_DYN] = uwsgi_dyn_loader;
@@ -1029,6 +1061,16 @@ void uwsgi_python_init_apps() {
#endif
}
PyObject *uwsgi_dict = get_uwsgi_pydict("uwsgi");
if (uwsgi_dict) {
up.after_req_hook = PyDict_GetItemString(uwsgi_dict, "after_req_hook");
if (up.after_req_hook) {
Py_INCREF(up.after_req_hook);
up.after_req_hook_args = PyTuple_New(0);
Py_INCREF(up.after_req_hook_args);
}
}
}
void uwsgi_python_master_fixup(int step) {
@@ -1073,6 +1115,9 @@ void uwsgi_python_enable_threads() {
up.gil_get = gil_real_get;
up.gil_release = gil_real_release;
up.swap_ts = simple_threaded_swap_ts;
up.reset_ts = simple_threaded_reset_ts;
if (uwsgi.threads > 1) {
up.swap_ts = threaded_swap_ts;
up.reset_ts = threaded_reset_ts;
@@ -1091,61 +1136,37 @@ void uwsgi_python_init_thread(int core_id) {
pthread_setspecific(up.upt_save_key, (void *) pts);
pthread_setspecific(up.upt_gil_key, (void *) pts);
#ifdef UWSGI_DEBUG
uwsgi_log("pts %d = %p\n", core_id, pts);
uwsgi_log("python ThreadState %d = %p\n", core_id, pts);
#endif
UWSGI_GET_GIL;
// call threading.currentThread (taken from mod_wsgi, but removes DECREFs as thread in uWSGI are fixed)
PyObject *threading_module = PyImport_ImportModule("threading");
if (threading_module) {
PyObject *threading_module_dict = PyModule_GetDict(threading_module);
if (threading_module_dict) {
#ifdef PYTHREE
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "current_thread");
#else
PyObject *threading_current = PyDict_GetItemString(threading_module_dict, "currentThread");
#endif
if (threading_current) {
PyObject *current_thread = PyEval_CallObject(threading_current, (PyObject *)NULL);
if (!current_thread) {
// ignore the error
PyErr_Clear();
}
else {
PyObject_SetAttrString(current_thread, "name", PyString_FromFormat("uWSGIWorker%dCore%d", uwsgi.mywid, core_id));
Py_INCREF(current_thread);
}
}
}
}
UWSGI_RELEASE_GIL;
}
int uwsgi_python_xml(char *node, char *content) {
PyThreadState *interpreter = NULL;
if (uwsgi.single_interpreter) {
interpreter = up.main_thread;
}
if (!strcmp("script", node)) {
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("file", node)) {
return init_uwsgi_app(LOADER_FILE, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("eval", node)) {
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("wsgi", node)) {
return init_uwsgi_app(LOADER_EVAL, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else if (!strcmp("module", node)) {
uwsgi.wsgi_req->module = content;
uwsgi.wsgi_req->module_len = strlen(content);
uwsgi.wsgi_req->callable = strchr(uwsgi.wsgi_req->module, ':');
if (uwsgi.wsgi_req->callable) {
uwsgi.wsgi_req->callable[0] = 0;
uwsgi.wsgi_req->callable++;
uwsgi.wsgi_req->callable_len = strlen(uwsgi.wsgi_req->callable);
uwsgi.wsgi_req->module_len = strlen(uwsgi.wsgi_req->module);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
else {
return init_uwsgi_app(LOADER_UWSGI, content, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
return 1;
}
else if (!strcmp("pyhome", node)) {
uwsgi.wsgi_req->pyhome = content;
uwsgi.wsgi_req->pyhome_len = strlen(content);
return 1;
}
else if (!strcmp("callable", node)) {
uwsgi.wsgi_req->callable = content;
uwsgi.wsgi_req->callable_len = strlen(content);
return init_uwsgi_app(LOADER_DYN, uwsgi.wsgi_req, uwsgi.wsgi_req, interpreter, PYTHON_APP_TYPE_WSGI);
}
return 0;
}
#ifndef UWSGI_PYPY
void uwsgi_python_suspend(struct wsgi_request *wsgi_req) {
@@ -1241,36 +1262,38 @@ clear:
return -1;
}
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
uint16_t uwsgi_python_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
UWSGI_GET_GIL;
uint8_t i;
PyObject *pyargs = PyTuple_New(argc);
PyObject *ret;
char *rv;
size_t rl;
PyObject *pyargs = PyTuple_New(argc);
PyObject *ret;
if (!pyargs)
return 0;
for (i = 0; i < argc; i++) {
PyTuple_SetItem(pyargs, i, PyString_FromString(argv[i]));
PyTuple_SetItem(pyargs, i, PyString_FromStringAndSize(argv[i], argvs[i]));
}
ret = python_call((PyObject *) func, pyargs, 0, NULL);
Py_DECREF(pyargs);
if (ret) {
if (PyString_Check(ret)) {
rv = PyString_AsString(ret);
rl = PyString_Size(ret);
if (rl <= 0xffff) {
if (rl <= 65536) {
memcpy(buffer, rv, rl);
Py_DECREF(ret);
UWSGI_RELEASE_GIL;
return rl;
}
}
Py_DECREF(ret);
}
if (PyErr_Occurred())
@@ -1376,13 +1399,35 @@ void uwsgi_python_fixup() {
uwsgi.p[30] = uwsgi_malloc( sizeof(struct uwsgi_plugin) );
memcpy(uwsgi.p[30], uwsgi.p[0], sizeof(struct uwsgi_plugin) );
uwsgi.p[30]->init_thread = NULL;
uwsgi.p[30]->atexit = NULL;
}
void uwsgi_python_hijack(void) {
// the pyshell will be execute only in the first worker
FILE *pyfile;
if (up.pyrun) {
uwsgi.workers[uwsgi.mywid].hijacked = 1;
UWSGI_GET_GIL;
pyfile = fopen(up.pyrun, "r");
if (!pyfile) {
uwsgi_error_open(up.pyrun);
exit(1);
}
PyRun_SimpleFile(pyfile, up.pyrun);
// could be never executed
exit(0);
}
#ifndef UWSGI_PYPY
if (up.pyshell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
uwsgi.workers[uwsgi.mywid].hijacked = 0;
return;
}
if (up.pyshell && uwsgi.mywid == 1) {
uwsgi.workers[uwsgi.mywid].hijacked = 1;
uwsgi.workers[uwsgi.mywid].hijacked_count++;
// re-map stdin to stdout and stderr if we are logging to a file
if (uwsgi.logfile) {
if (dup2(0, 1) < 0) {
@@ -1394,7 +1439,15 @@ void uwsgi_python_hijack(void) {
}
UWSGI_GET_GIL;
PyImport_ImportModule("readline");
PyRun_InteractiveLoop(stdin, "uwsgi");
int ret = PyRun_InteractiveLoop(stdin, "uwsgi");
if (up.pyshell_oneshot) {
exit(UWSGI_DE_HIJACKED_CODE);
}
if (ret == 0) {
exit(UWSGI_QUIET_CODE);
}
exit(0);
}
#endif
@@ -1450,10 +1503,10 @@ struct uwsgi_plugin python_plugin = {
.init = uwsgi_python_init,
.post_fork = uwsgi_python_post_fork,
.options = uwsgi_python_options,
.manage_opt = uwsgi_python_manage_options,
.short_options = "w:O:H:J:",
.request = uwsgi_request_wsgi,
.after_request = uwsgi_after_request_wsgi,
.preinit_apps = uwsgi_python_preinit_apps,
.init_apps = uwsgi_python_init_apps,
.fixup = uwsgi_python_fixup,
@@ -1463,7 +1516,6 @@ struct uwsgi_plugin python_plugin = {
.enable_threads = uwsgi_python_enable_threads,
.init_thread = uwsgi_python_init_thread,
.manage_xml = uwsgi_python_xml,
.magic = uwsgi_python_magic,
@@ -1483,8 +1535,9 @@ struct uwsgi_plugin python_plugin = {
.spooler = uwsgi_python_spooler,
.atexit = uwsgi_python_atexit,
.code_string = uwsgi_python_code_string,
.help = uwsgi_python_help,
};
+43 -19
View File
@@ -64,24 +64,51 @@ void init_pyargv() {
char *ap;
char *argv0 = "uwsgi";
if (up.pyrun) {
argv0 = up.pyrun;
}
#ifdef PYTHREE
wchar_t pname[6];
mbstowcs(pname, "uwsgi", 6);
up.py_argv[0] = pname;
wchar_t *pname = uwsgi_calloc(strlen(argv0)+1);
mbstowcs(pname, argv0, strlen(argv0)+1);
#else
up.py_argv[0] = "uwsgi";
char *pname = argv0;
#endif
up.argc = 1;
if (up.argv != NULL) {
#ifdef PYTHREE
wchar_t *wcargv = malloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
if (!wcargv) {
uwsgi_error("malloc()");
exit(1);
if (up.argv) {
char *tmp_ptr = uwsgi_str(up.argv);
#ifdef __sun__
// FIX THIS !!!
ap = strtok(tmp_ptr, " ");
while ((ap = strtok(NULL, " ")) != NULL) {
#else
while ((ap = strsep(&tmp_ptr, " \t")) != NULL) {
#endif
if (*ap != '\0') {
up.argc++;
}
}
memset(wcargv, 0, sizeof( wchar_t ) * (strlen(up.argv)+1));
free(tmp_ptr);
}
#ifdef PYTHREE
up.py_argv = uwsgi_calloc(sizeof(wchar_t *) * up.argc+1);
#else
up.py_argv = uwsgi_calloc(sizeof(char *) * up.argc+1);
#endif
up.py_argv[0] = pname;
if (up.argv) {
up.argc = 1;
#ifdef PYTHREE
wchar_t *wcargv = uwsgi_calloc( sizeof( wchar_t ) * (strlen(up.argv)+1));
#endif
#ifdef __sun__
@@ -89,7 +116,7 @@ void init_pyargv() {
ap = strtok(up.argv, " ");
while ((ap = strtok(NULL, " ")) != NULL) {
#else
while ((ap = strsep(&up.argv, " \t")) != NULL) {
while ((ap = strsep(&up.argv, " \t")) != NULL) {
#endif
if (*ap != '\0') {
#ifdef PYTHREE
@@ -100,14 +127,11 @@ void init_pyargv() {
#endif
up.argc++;
}
if (up.argc + 1 > MAX_PYARGV)
break;
}
}
#ifndef UWSGI_PYPY
PySys_SetArgv(up.argc, up.py_argv);
#endif
}
PySys_SetArgv(up.argc, up.py_argv);
PyObject *sys_dict = get_uwsgi_pydict("sys");
if (!sys_dict) {
File diff suppressed because it is too large Load Diff
+14 -26
View File
@@ -3,25 +3,6 @@
#include <frameobject.h>
#define MAX_PYMODULE_ALIAS 64
#define MAX_PYARGV 10
#define LONG_ARGS_PYTHON_BASE 17000 + ((0 + 1) * 1000)
#define LONG_ARGS_PYTHONPATH LONG_ARGS_PYTHON_BASE + 1
#define LONG_ARGS_PASTE LONG_ARGS_PYTHON_BASE + 2
#define LONG_ARGS_PYARGV LONG_ARGS_PYTHON_BASE + 3
#define LONG_ARGS_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 4
#define LONG_ARGS_RELOAD_OS_ENV LONG_ARGS_PYTHON_BASE + 5
#define LONG_ARGS_PYIMPORT LONG_ARGS_PYTHON_BASE + 6
#define LONG_ARGS_POST_PYMODULE_ALIAS LONG_ARGS_PYTHON_BASE + 7
#define LONG_ARGS_WEB3 LONG_ARGS_PYTHON_BASE + 8
#define LONG_ARGS_PUMP LONG_ARGS_PYTHON_BASE + 9
#define LONG_ARGS_WSGI_LITE LONG_ARGS_PYTHON_BASE + 10
#define LONG_ARGS_PYSHELL LONG_ARGS_PYTHON_BASE + 11
#define LONG_ARGS_SPOOLER_PYIMPORT LONG_ARGS_PYTHON_BASE + 12
#define LONG_ARGS_PYTHON_RUN LONG_ARGS_PYTHON_BASE + 13
#define PYTHON_APP_TYPE_WSGI 0
#define PYTHON_APP_TYPE_WEB3 1
#define PYTHON_APP_TYPE_WSGI2 2
@@ -117,9 +98,9 @@ struct uwsgi_python {
int argc;
#ifdef PYTHREE
wchar_t *py_argv[MAX_PYARGV];
wchar_t **py_argv;
#else
char *py_argv[MAX_PYARGV];
char **py_argv;
#endif
PyObject *wsgi_spitout;
@@ -130,11 +111,15 @@ struct uwsgi_python {
char *test_module;
int pyshell;
int pyshell_oneshot;
struct uwsgi_string_list *python_path;
struct uwsgi_string_list *import_list;
struct uwsgi_string_list *shared_import_list;
struct uwsgi_string_list *spooler_import_list;
struct uwsgi_string_list *post_pymodule_alias;
struct uwsgi_string_list *pymodule_alias;
PyObject *loader_dict;
PyObject* (*loaders[LOADER_MAX]) (void *);
@@ -142,6 +127,7 @@ struct uwsgi_python {
char *wsgi_config;
char *file_config;
char *paste;
int paste_logger;
char *eval;
char *web3;
@@ -173,10 +159,7 @@ struct uwsgi_python {
PyObject *workers_tuple;
PyObject *embedded_dict;
PyObject *embedded_args;
PyObject *fastfuncslist;
char *pymodule_alias[MAX_PYMODULE_ALIAS];
int pymodule_alias_cnt;
int pep3333_input;
@@ -184,6 +167,11 @@ struct uwsgi_python {
int reload_os_env;
PyObject *after_req_hook;
PyObject *after_req_hook_args;
char *pyrun;
};
@@ -210,8 +198,6 @@ PyObject *python_call(PyObject *, PyObject *, int, struct wsgi_request *);
#ifdef UWSGI_SENDFILE
PyObject *py_uwsgi_sendfile(PyObject *, PyObject *);
ssize_t uwsgi_sendfile(struct wsgi_request *);
ssize_t uwsgi_do_sendfile(int, int, size_t, size_t, off_t*, int);
#endif
PyObject *py_uwsgi_write(PyObject *, PyObject *);
@@ -259,8 +245,10 @@ PyObject *uwsgi_pyimport_by_filename(char *, char *);
void threaded_swap_ts(struct wsgi_request *, struct uwsgi_app *);
void simple_swap_ts(struct wsgi_request *, struct uwsgi_app *);
void simple_threaded_swap_ts(struct wsgi_request *, struct uwsgi_app *);
void threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
void simple_reset_ts(struct wsgi_request *, struct uwsgi_app *);
void simple_threaded_reset_ts(struct wsgi_request *, struct uwsgi_app *);
int uwsgi_python_profiler_call(PyObject *, PyFrameObject *, int, PyObject *);
+1 -1
View File
@@ -192,12 +192,12 @@ int uwsgi_response_subhandler_web3(struct wsgi_request *wsgi_req) {
UWSGI_RELEASE_GIL
return UWSGI_AGAIN;
}
#endif
}
else {
uwsgi_log("invalid Web3 response.\n");
goto clear;
}
#endif
}
+39 -1
View File
@@ -229,7 +229,7 @@ static PyMethodDef uwsgi_Input_methods[] = {
PyTypeObject uwsgi_InputType = {
PyVarObject_HEAD_INIT(NULL, 0)
"uwsgi._Input", /*tp_name */
"uwsgi._Input", /*tp_name */
sizeof(uwsgi_Input), /*tp_basicsize */
0, /*tp_itemsize */
(destructor) uwsgi_Input_free, /*tp_dealloc */
@@ -513,6 +513,24 @@ clear2:
void uwsgi_after_request_wsgi(struct wsgi_request *wsgi_req) {
if (up.after_req_hook) {
if (uwsgi.harakiri_no_arh) {
// leave harakiri mode
if (uwsgi.workers[uwsgi.mywid].harakiri > 0)
set_harakiri(0);
}
UWSGI_GET_GIL
PyObject *arh = python_call(up.after_req_hook, up.after_req_hook_args, 0, NULL);
if (!arh) {
PyErr_Print();
}
else {
Py_DECREF(arh);
}
PyErr_Clear();
UWSGI_RELEASE_GIL
}
if (uwsgi.shared->options[UWSGI_OPTION_LOGGING] || wsgi_req->log_this) {
log_request(wsgi_req);
}
@@ -599,3 +617,23 @@ void simple_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
PyThreadState_Swap(wi->interpreter);
}
}
void simple_threaded_reset_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
// restoring main interpreter
UWSGI_GET_GIL
PyThreadState_Swap(up.main_thread);
UWSGI_RELEASE_GIL
}
}
void simple_threaded_swap_ts(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {
if (uwsgi.single_interpreter == 0 && wi->interpreter != up.main_thread) {
// set the interpreter
UWSGI_GET_GIL
PyThreadState_Swap(wi->interpreter);
UWSGI_RELEASE_GIL
}
}
-10
View File
@@ -156,18 +156,8 @@ void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_
PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);
#ifdef UWSGI_ROUTING
uwsgi_log("routing %d routes %d\n", uwsgi.routing, uwsgi.nroutes);
if (uwsgi.routing && uwsgi.nroutes > 0) {
check_route(uwsgi, wsgi_req);
}
#endif
// call
PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
return python_call(wsgi_req->async_app, wsgi_req->async_args, up.catch_exceptions, wsgi_req);
}
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python24'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.4-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python24_plugin')
LDFLAGS = os.popen('python2.4-config --ldflags').read().rstrip().split()
LIBS = os.popen('python2.4-config --libs').read().rstrip().split()
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python25'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.5-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python25_plugin')
LDFLAGS = os.popen('python2.5-config --ldflags').read().rstrip().split()
LIBS = os.popen('python2.5-config --libs').read().rstrip().split()
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python26'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.6-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python26_plugin')
LDFLAGS = os.popen('python2.6-config --ldflags').read().rstrip().split()
LIBS = os.popen('python2.6-config --libs').read().rstrip().split()
-12
View File
@@ -1,12 +0,0 @@
import os,sys
NAME='python27'
GCC_LIST = map(lambda x: '../python/' + x, ['python_plugin', 'pyutils', 'pyloader', 'wsgi_handlers', 'wsgi_headers', 'wsgi_subhandler', 'web3_subhandler', 'pump_subhandler', 'gil', 'uwsgi_pymodule', 'profiler', 'symimporter'])
CFLAGS = os.popen('python2.7-config --cflags').read().rstrip().split()
CFLAGS.append('-Wno-unused-parameter')
CFLAGS.append('-Wno-strict-prototypes')
CFLAGS.append('-Dpython_plugin=python27_plugin')
LDFLAGS = os.popen('python2.7-config --ldflags').read().rstrip().split()
LIBS = os.popen('python2.7-config --libs').read().rstrip().split()

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