Compare commits

..
105 Commits
Author SHA1 Message Date
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
61 changed files with 4511 additions and 1375 deletions
+5
View File
@@ -38,3 +38,8 @@ fb168b0b86169219aa9b8e40f0caa6297cf34dbc 0.9.9-rc1
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
+2
View File
@@ -15,3 +15,5 @@ Luigi Scarso
Corey Farwell
Charles Duffy
Lukas Lalinsky
Steven Fernandez
Łukasz Mierzwa
+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]
+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}
};
+2 -2
View File
@@ -3,7 +3,7 @@ xml = true
ini = true
yaml = true
json = auto
sqlite3 = false
sqlite3 = auto
zeromq = auto
snmp = true
sctp = false
@@ -27,7 +27,7 @@ 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
as_shared_library = false
locking = auto
+3 -7
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) {
@@ -91,7 +86,8 @@ void uwsgi_init_cache() {
uwsgi.cache_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.cache_lock);
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) {
+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);
}
+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)
+9 -6
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()");
@@ -512,6 +514,7 @@ reconnect:
uwsgi_error("glob()");
exit(1);
}
globfree(&g);
emperor_absolute_dir = realpath(".", NULL);
}
@@ -614,10 +617,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);
@@ -647,7 +648,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 +747,7 @@ reconnect:
}
}
globfree(&g);
}
}
@@ -847,6 +849,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()));
+45 -1
View File
@@ -64,7 +64,7 @@ void log_request(struct wsgi_request *wsgi_req) {
#endif
// mark route() requests
if (wsgi_req->status == -1) {
if (wsgi_req->status == -17) {
via = msg3;
}
@@ -224,3 +224,47 @@ void get_memusage(uint64_t *rss, uint64_t *vsz) {
#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;
}
+694 -622
View File
File diff suppressed because it is too large Load Diff
+22
View File
@@ -102,6 +102,9 @@ 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)
@@ -317,6 +320,9 @@ void uwsgi_send_stats(int fd) {
stats_send_llu("\"listen_queue\": %llu,\n", uwsgi.shared->ti.tcpi_unacked);
#endif
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()));
@@ -324,6 +330,22 @@ void uwsgi_send_stats(int fd) {
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, "\"workers\": [\n");
for (i = 0; i < uwsgi.numproc; i++) {
+5
View File
@@ -94,7 +94,9 @@ check:
linkpath_buf[linkpath_size] = '\0';
strcpy(linkpath, linkpath_buf);
} 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, '/');
@@ -139,6 +141,9 @@ check:
}
free(plugin_name);
free(plugin_entry_symbol);
if (up->on_load)
up->on_load();
return plugin_handle;
}
uwsgi_log( "%s\n", dlerror());
+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);
}
}
}
+760 -43
View File
@@ -1,27 +1,446 @@
#include "../../uwsgi.h"
#include <wordexp.h>
extern struct uwsgi_server uwsgi;
char *cgi_docroot;
struct uwsgi_cgi {
struct uwsgi_dyn_dict *mountpoint;
struct uwsgi_dyn_dict *helpers;
int buffer_size;
int timeout;
struct uwsgi_string_list *index;
struct uwsgi_string_list *allowed_ext;
struct uwsgi_string_list *unset;
struct uwsgi_string_list *loadlib;
int optimize;
int has_mountpoints;
struct uwsgi_dyn_dict *default_cgi;
int path_info;
} uc ;
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 1000)
#define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1
#define LONG_ARGS_CGI_BASE 17000 + ((9 + 1) * 1000)
#define LONG_ARGS_CGI LONG_ARGS_CGI_BASE + 1
#define LONG_ARGS_CGI_MAP_HELPER LONG_ARGS_CGI_BASE + 2
#define LONG_ARGS_CGI_BUFFER_SIZE LONG_ARGS_CGI_BASE + 3
#define LONG_ARGS_CGI_TIMEOUT LONG_ARGS_CGI_BASE + 4
#define LONG_ARGS_CGI_INDEX LONG_ARGS_CGI_BASE + 5
#define LONG_ARGS_CGI_ALLOWED_EXT LONG_ARGS_CGI_BASE + 6
#define LONG_ARGS_CGI_UNSET LONG_ARGS_CGI_BASE + 7
#define LONG_ARGS_CGI_LOADLIB LONG_ARGS_CGI_BASE + 8
struct option uwsgi_cgi_options[] = {
{"cgi", required_argument, 0, LONG_ARGS_CGI},
{"cgi-map-helper", required_argument, 0, LONG_ARGS_CGI_MAP_HELPER},
{"cgi-helper", required_argument, 0, LONG_ARGS_CGI_MAP_HELPER},
{"cgi-buffer-size", required_argument, 0, LONG_ARGS_CGI_BUFFER_SIZE},
{"cgi-timeout", required_argument, 0, LONG_ARGS_CGI_TIMEOUT},
{"cgi-index", required_argument, 0, LONG_ARGS_CGI_INDEX},
{"cgi-allowed-ext", required_argument, 0, LONG_ARGS_CGI_ALLOWED_EXT},
{"cgi-unset", required_argument, 0, LONG_ARGS_CGI_UNSET},
{"cgi-loadlib", required_argument, 0, LONG_ARGS_CGI_LOADLIB},
{"cgi-optimize", no_argument, &uc.optimize, 1},
{"cgi-optimized", no_argument, &uc.optimize, 1},
{"cgi-path-info", no_argument, &uc.path_info, 1},
{0, 0, 0, 0},
};
void uwsgi_cgi_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\n\r\nNot Found", 35);
}
void uwsgi_cgi_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\n\r\nForbidden", 35);
}
void uwsgi_cgi_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++;
}
}
void uwsgi_cgi_apps() {
struct uwsgi_dyn_dict *udd = uc.mountpoint;
struct stat st;
while(udd) {
if (udd->vallen) {
if (uc.optimize) {
udd->value = realpath(udd->value, NULL);
if (!udd->value) {
uwsgi_log("unable to find CGI path %.*s\n", udd->vallen, udd->value);
exit(1);
}
udd->vallen = strlen(udd->value);
udd->status = 1;
if (stat(udd->value, &st)) {
uwsgi_error("stat()");
uwsgi_log("something horrible happened during CGI initialization\n");
exit(1);
}
if (!S_ISDIR(st.st_mode)) {
udd->status = 2;
}
}
uc.has_mountpoints = 1;
uwsgi_log("initialized CGI mountpoint: %.*s = %.*s\n", udd->keylen, udd->key, udd->vallen, udd->value);
}
else {
if (uc.optimize) {
udd->key = realpath(udd->key, NULL);
if (!udd->key) {
uwsgi_log("unable to find CGI path %.*s\n", udd->keylen, udd->key);
exit(1);
}
udd->keylen = strlen(udd->key);
udd->status = 1;
if (stat(udd->key, &st)) {
uwsgi_error("stat()");
uwsgi_log("something horrible happened during CGI initialization\n");
exit(1);
}
if (!S_ISDIR(st.st_mode)) {
udd->status = 2;
}
}
uwsgi_log("initialized CGI path: %.*s\n", udd->keylen, udd->key);
uc.default_cgi = udd;
}
udd = udd->next;
}
}
int uwsgi_cgi_init(){
void (*cgi_sym)(void);
uwsgi_log("initialized CGI engine\n");
if (!uc.buffer_size) uc.buffer_size = 65536;
if (!uc.timeout) uc.timeout = 60;
struct uwsgi_string_list *ll = uc.loadlib;
while(ll) {
char *colon = strchr(ll->value, ':');
if (!colon) {
uwsgi_log("invalid cgi-loadlib syntax, must be in the form lib:func\n");
exit(1);
}
*colon = 0;
void *cgi_lib = dlopen(ll->value, RTLD_NOW | RTLD_GLOBAL);
if (!cgi_lib) {
uwsgi_log( "cgi-loadlib: %s\n", dlerror());
exit(1);
}
cgi_sym = dlsym(cgi_lib, colon+1);
if (!cgi_sym) {
uwsgi_log("unknown symbol %s in lib %s\n", colon+1, ll->value);
exit(1);
}
cgi_sym();
uwsgi_log("[cgi-loadlib] loaded symbol %s from %s\n", colon+1, ll->value);
*colon = ':';
ll = ll->next;
}
return 0;
}
char *uwsgi_cgi_get_helper(char *filename) {
struct uwsgi_dyn_dict *helpers = uc.helpers;
size_t len = strlen(filename);
while(helpers) {
if (len >= (size_t) helpers->keylen) {
if (!uwsgi_strncmp((filename+len)-helpers->keylen, helpers->keylen, helpers->key, helpers->keylen)) {
return helpers->value;
}
}
helpers = helpers->next;
}
return NULL;
}
int uwsgi_cgi_parse(struct wsgi_request *wsgi_req, char *buf, size_t len) {
size_t i;
char *key = buf, *value = NULL;
size_t header_size = 0;
int status_sent = 0;
struct uwsgi_string_list *ah = uwsgi.additional_headers;
struct iovec iov[4];
for(i=0;i<len;i++) {
// end of a line
if (buf[i] == '\n') {
// end of headers
if (key == NULL) {
goto send_body;
}
// invalid header
else if (value == NULL) {
return -1;
}
header_size = (buf+i) - key;
// security check
if (buf+i > buf) {
if ((buf[i-1]) == '\r') {
header_size--;
}
}
#ifdef UWSGI_DEBUG
uwsgi_log("found CGI header: %.*s\n", header_size, key);
#endif
if (status_sent == 0) {
// "Status: NNN"
if (header_size >= 11) {
if (!strncasecmp("Status: ", key, 8)) {
wsgi_req->status = uwsgi_str3_num(key+8);
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
iov[1].iov_base = " ";
iov[1].iov_len = 1;
iov[2].iov_base = key+8;
iov[2].iov_len = header_size - 8;
iov[3].iov_base = "\r\n";
iov[3].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 4);
status_sent = 1;
key = NULL;
value = NULL;
continue;
}
}
}
// default status
if (status_sent == 0) {
// Location: X
if (header_size >= 11) {
if (!strncasecmp("Location: ", key, 10)) {
wsgi_req->status = 302;
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
iov[1].iov_base = " 302 Found\r\n";
iov[1].iov_len = 12;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
status_sent = 1;
}
}
if (status_sent == 0) {
wsgi_req->status = 200;
iov[0].iov_base = wsgi_req->protocol;
iov[0].iov_len = wsgi_req->protocol_len;
iov[1].iov_base = " 200 OK\r\n";
iov[1].iov_len = 9;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, iov, 2);
status_sent = 1;
}
}
iov[0].iov_base = key;
iov[0].iov_len = header_size;
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++;
key = NULL;
value = NULL;
}
else if (buf[i] == ':') {
value = buf+i;
}
else if (buf[i] != '\r') {
if (key == NULL) {
key = buf + i;
}
}
}
return -1;
send_body:
while(ah) {
iov[0].iov_base = ah->value;
iov[0].iov_len = ah->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++;
ah = ah->next;
}
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
if (len-i > 0) {
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, buf+i, len-i);
}
return 0;
}
char *uwsgi_cgi_get_docroot(char *path_info, uint16_t path_info_len, int *need_free, int *is_a_file, int *discard_base, char **script_name) {
struct uwsgi_dyn_dict *udd = uc.mountpoint, *choosen_udd = NULL;
int best_found = 0;
struct stat st;
char *path = NULL;
if (uc.has_mountpoints) {
while(udd) {
if (udd->vallen) {
if (!uwsgi_starts_with(path_info, path_info_len, udd->key, udd->keylen) && udd->keylen > best_found) {
best_found = udd->keylen ;
choosen_udd = udd;
path = udd->value;
*script_name = udd->key;
*discard_base = udd->keylen;
if (udd->key[udd->keylen-1] == '/') {
*discard_base = *discard_base-1;
}
}
}
udd = udd->next;
}
}
if (choosen_udd == NULL) {
choosen_udd = uc.default_cgi;
if (!choosen_udd) return NULL;
path = choosen_udd->key;
}
if (choosen_udd->status == 0) {
char *tmp_udd = realpath(path, NULL);
if (!tmp_udd) {
return NULL;
}
if (stat(tmp_udd, &st)) {
uwsgi_error("stat()");
free(tmp_udd);
return NULL;
}
if (!S_ISDIR(st.st_mode)) {
*is_a_file = 1;
}
*need_free = 1;
return tmp_udd;
}
if (choosen_udd->status == 2)
*is_a_file = 1;
return path;
}
int uwsgi_cgi_walk(struct wsgi_request *wsgi_req, char *full_path, char *docroot, size_t docroot_len, int discard_base, char **path_info) {
// and now start walking...
uint16_t i;
char *ptr = wsgi_req->path_info+discard_base;
char *dst = full_path+docroot_len;
char *part = ptr;
int part_size = 0;
struct stat st;
if (ptr[0] == '/') part_size++;
for(i=0;i<wsgi_req->path_info_len-discard_base;i++) {
if (ptr[i] == '/') {
memcpy(dst, part, part_size-1);
*(dst+part_size-1) = 0;
if (stat(full_path, &st)) {
uwsgi_cgi_404(wsgi_req);
return -1;
}
// not a directory, stop walking
if (!S_ISDIR(st.st_mode)) {
if (i < (wsgi_req->path_info_len-discard_base)-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;
return 1;
}
@@ -30,10 +449,21 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
int i;
pid_t cgi_pid;
int waitpid_status;
char *argv[2];
char *argv[3];
char full_path[PATH_MAX];
char tmp_path[PATH_MAX];
int cgi_pipe[2];
ssize_t len;
struct stat cgi_stat;
int need_free = 0;
int is_a_file = 0;
int discard_base = 0;
size_t docroot_len = 0;
size_t full_path_len = 0;
char *helper = NULL;
char *command = NULL;
char *path_info = NULL;
char *script_name = NULL;
/* Standard CGI request */
if (!wsgi_req->uh.pktsize) {
@@ -43,28 +473,141 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid CGI request. skip.\n");
return -1;
}
// check for file availability (and 'runnability')
char *path_info = uwsgi_concat4n(cgi_docroot, strlen(cgi_docroot), "/", 1,wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
uwsgi_log("requested %s %s\n", path_info, realpath(path_info, full_path));
char *docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name);
if (access(full_path, R_OK)) {
wsgi_req->status = 404;
wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 404 Not Found\r\n\r\n", 26);
if (docroot == NULL) {
uwsgi_cgi_404(wsgi_req);
return UWSGI_OK;
}
if (access(full_path, X_OK)) {
wsgi_req->status = 500;
wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 500 Internal Server Error\r\n\r\n", 26);
docroot_len = strlen(docroot);
memcpy(full_path, docroot, docroot_len);
if (!is_a_file) {
*(full_path+docroot_len) = '/';
*(full_path+docroot_len+1) = 0;
if (uwsgi_cgi_walk(wsgi_req, full_path, docroot, docroot_len, discard_base, &path_info)) {
if (need_free)
free(docroot);
return UWSGI_OK;
}
if (realpath(full_path, tmp_path) == NULL) {
if (need_free)
free(docroot);
uwsgi_cgi_404(wsgi_req);
return UWSGI_OK;
}
full_path_len = strlen(tmp_path);
// add +1 to copy the null byte
memcpy(full_path, tmp_path, full_path_len+1);
if (uwsgi_starts_with(full_path, full_path_len, docroot, docroot_len)) {
if (need_free)
free(docroot);
uwsgi_log("CGI security error: %s is not under %s\n", full_path, docroot);
return -1;
}
}
else {
*(full_path+docroot_len) = 0;
path_info = wsgi_req->path_info+discard_base;
}
if (stat(full_path, &cgi_stat)) {
uwsgi_cgi_404(wsgi_req);
if (need_free)
free(docroot);
return UWSGI_OK;
}
if (S_ISDIR(cgi_stat.st_mode)) {
// add / to directories
if (wsgi_req->path_info_len == 0 || wsgi_req->path_info[wsgi_req->path_info_len-1] != '/') {
uwsgi_cgi_redirect_to_slash(wsgi_req);
if (need_free)
free(docroot);
return UWSGI_OK;
}
struct uwsgi_string_list *ci = uc.index;
full_path[full_path_len] = '/';
full_path_len++;
int found = 0;
while(ci) {
if (full_path_len + ci->len + 1 < PATH_MAX) {
// add + 1 to ensure null byte
memcpy(full_path+full_path_len, ci->value, ci->len + 1);
if (!access(full_path, R_OK)) {
found = 1;
break;
}
}
ci = ci->next;
}
if (!found) {
uwsgi_cgi_404(wsgi_req);
if (need_free)
free(docroot);
return UWSGI_OK;
}
}
else {
full_path_len = strlen(full_path);
}
int cgi_allowed = 1;
struct uwsgi_string_list *allowed = uc.allowed_ext;
while(allowed) {
cgi_allowed = 0;
if (full_path_len >= allowed->len) {
if (!uwsgi_strncmp(full_path+(full_path_len-allowed->len), allowed->len, allowed->value, allowed->len)) {
cgi_allowed = 1;
break;
}
}
allowed = allowed->next;
}
if (!cgi_allowed) {
uwsgi_cgi_403(wsgi_req);
if (need_free)
free(docroot);
return UWSGI_OK;
}
if (is_a_file) {
command = docroot;
}
else {
command = full_path;
helper = uwsgi_cgi_get_helper(full_path);
if (helper == NULL) {
if (access(full_path, X_OK)) {
uwsgi_error("access()");
uwsgi_cgi_403(wsgi_req);
if (need_free)
free(docroot);
return UWSGI_OK;
}
}
}
if (pipe(cgi_pipe)) {
if (need_free)
free(docroot);
uwsgi_error("pipe()");
return UWSGI_OK;
}
@@ -73,48 +616,92 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
if (cgi_pid < 0) {
uwsgi_error("fork()");
if (need_free)
free(docroot);
return -1;
}
if (cgi_pid > 0) {
// close input
close(wsgi_req->poll.fd);
wsgi_req->fd_closed = 1;
if (need_free)
free(docroot);
close(cgi_pipe[1]);
// wait for data
char startbuf[8];
char *ptr = startbuf;
int remains = 8;
char *headers_buf = uwsgi_malloc(uc.buffer_size);
char *ptr = headers_buf;
size_t remains = uc.buffer_size;
int completed = 0;
while(remains > 0) {
uwsgi_log("waiting for fd\n");
int ret = uwsgi_waitfd(cgi_pipe[0], 10);
uwsgi_log("data available\n");
int ret = uwsgi_waitfd(cgi_pipe[0], uc.timeout);
if (ret > 0) {
len = read(cgi_pipe[0], ptr, remains);
if (len > 0) {
ptr+=len;
remains -= len;
}
else if (len == 0) {
completed = 1;
break;
}
else {
uwsgi_error("read()");
goto clear;
}
continue;
}
else if (ret == 0) {
uwsgi_log("CGI timeout !!!\n");
goto clear;
}
break;
}
uwsgi_log("STARTBUF %.*s\n", 8, startbuf);
if (!memcmp(startbuf, "Status: ", 8)) {
wsgi_req->socket->proto_write(wsgi_req, "HTTP/1.1 "
if (uwsgi_cgi_parse(wsgi_req, headers_buf, uc.buffer_size-remains)) {
uwsgi_log("invalid CGI output !!!\n");
goto clear;
}
// now wait for fd
if (waitpid(cgi_pid, &waitpid_status ,0) > 0) {
uwsgi_log("CGI FINISHED\n");
while (!completed) {
int ret = uwsgi_waitfd(cgi_pipe[0], uc.timeout);
if (ret > 0) {
len = read(cgi_pipe[0], headers_buf, uc.buffer_size);
if (len > 0) {
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, headers_buf, len);
}
// end of output
else if (len == 0) {
break;
}
else {
uwsgi_error("read()");
goto clear;
}
continue;
}
else if (ret == 0) {
uwsgi_log("CGI timeout !!!\n");
goto clear;
}
break;
}
return 0;
clear:
free(headers_buf);
close(cgi_pipe[0]);
// now wait for process exit/death
if (waitpid(cgi_pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
return UWSGI_OK;
}
// close all the fd except wsgi_req->poll.fd and 2;
for(i=0;i< (int)uwsgi.max_fd;i++) {
if (i != wsgi_req->poll.fd && i != 2 && i != cgi_pipe[0] && i != cgi_pipe[1]) {
if (i != wsgi_req->poll.fd && i != 2 && i != cgi_pipe[1]) {
close(i);
}
}
@@ -125,10 +712,12 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
close(wsgi_req->poll.fd);
}
#ifdef UWSGI_DEBUG
uwsgi_log("mapping cgi_pipe %d to 1\n", cgi_pipe[1]);
#endif
dup2(cgi_pipe[1],1);
// fill cgi env
for(i=0;i<wsgi_req->var_cnt;i++) {
// no need to free the putenv() memory
@@ -139,16 +728,109 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
}
argv[0] = full_path;
argv[1] = NULL;
if (execv(argv[0], argv)) {
uwsgi_error("execv()");
if (setenv("GATEWAY_INTERFACE", "CGI/1.1", 0)) {
uwsgi_error("setenv()");
}
if (setenv("SERVER_SOFTWARE", uwsgi_concat2("uWSGI/", UWSGI_VERSION), 0)) {
uwsgi_error("setenv()");
}
// for newer php
if (setenv("REDIRECT_STATUS", "200", 0)) {
uwsgi_error("setenv()");
}
if (path_info && wsgi_req->path_info_len-discard_base > 0) {
if (setenv("PATH_INFO", uwsgi_concat2n(path_info, wsgi_req->path_info_len-discard_base, "", 0), 1)) {
uwsgi_error("setenv()");
}
if (setenv("PATH_TRANSLATED", uwsgi_concat4n(docroot, docroot_len, "/", 1, path_info, wsgi_req->path_info_len-discard_base, "", 0) , 1)) {
uwsgi_error("setenv()");
}
}
else {
unsetenv("PATH_INFO");
unsetenv("PATH_TRANSLATED");
}
if (is_a_file) {
if (setenv("DOCUMENT_ROOT", uwsgi.cwd, 0)) {
uwsgi_error("setenv()");
}
if (setenv("SCRIPT_FILENAME", docroot, 0)) {
uwsgi_error("setenv()");
}
if (script_name && discard_base > 1) {
if (setenv("SCRIPT_NAME", uwsgi_concat2n(script_name, discard_base, "", 0), 1)) {
uwsgi_error("setenv()");
}
}
}
else {
if (setenv("DOCUMENT_ROOT", docroot, 0)) {
uwsgi_error("setenv()");
}
if (setenv("SCRIPT_FILENAME", full_path, 0)) {
uwsgi_error("setenv()");
}
if (setenv("SCRIPT_NAME", full_path+(docroot_len-discard_base), 1)) {
uwsgi_error("setenv()");
}
char *base = uwsgi_get_last_char(full_path, '/');
if (base) {
// a little trick :P
*base = 0;
if (chdir(full_path)) {
uwsgi_error("chdir()");
}
*base = '/';
}
else {
if (chdir(docroot)) {
uwsgi_error("chdir()");
}
}
}
struct uwsgi_string_list *drop_env = uc.unset;
while(drop_env) {
unsetenv(drop_env->value);
drop_env = drop_env->next;
}
if (helper) {
if (!uwsgi_starts_with(helper, strlen(helper), "sym://", 6)) {
void (*cgi_func)(char *) = dlsym(RTLD_DEFAULT, helper+6);
if (cgi_func) {
cgi_func(command);
}
else {
uwsgi_log("unable to find symbol %s\n", helper+6);
}
exit(0);
}
argv[0] = helper;
argv[1] = command;
argv[2] = NULL;
}
else {
argv[0] = command;
argv[1] = NULL;
}
if (execvp(argv[0], argv)) {
uwsgi_error("execvp()");
}
// never here
exit(1);
return 0;
}
@@ -160,10 +842,44 @@ void uwsgi_cgi_after_request(struct wsgi_request *wsgi_req) {
int uwsgi_cgi_manage_options(int i, char *optarg) {
char *value;
switch(i) {
case LONG_ARGS_CGI:
cgi_docroot = optarg;
value = strchr(optarg, '=');
if (!value) {
uwsgi_dyn_dict_new(&uc.mountpoint, optarg, strlen(optarg), NULL, 0);
}
else {
uwsgi_dyn_dict_new(&uc.mountpoint, optarg, value-optarg, value+1, strlen(value+1));
}
return 1;
case LONG_ARGS_CGI_BUFFER_SIZE:
uc.buffer_size = atoi(optarg);
return 1;
case LONG_ARGS_CGI_TIMEOUT:
uc.timeout = atoi(optarg);
return 1;
case LONG_ARGS_CGI_INDEX:
uwsgi_string_new_list(&uc.index, optarg);
return 1;
case LONG_ARGS_CGI_ALLOWED_EXT:
uwsgi_string_new_list(&uc.allowed_ext, optarg);
return 1;
case LONG_ARGS_CGI_LOADLIB:
uwsgi_string_new_list(&uc.loadlib, uwsgi_str(optarg));
return 1;
case LONG_ARGS_CGI_UNSET:
uwsgi_string_new_list(&uc.unset, optarg);
return 1;
case LONG_ARGS_CGI_MAP_HELPER:
value = strchr(optarg, '=');
if (!value) {
uwsgi_log("invalid CGI helper syntax, must be ext=command\n");
exit(1);
}
uwsgi_dyn_dict_new(&uc.helpers, optarg, value-optarg, value+1, strlen(value+1));
return 1;
}
return 0;
@@ -175,6 +891,7 @@ struct uwsgi_plugin cgi_plugin = {
.name = "cgi",
.modifier1 = 9,
.init = uwsgi_cgi_init,
.init_apps = uwsgi_cgi_apps,
.options = uwsgi_cgi_options,
.manage_opt = uwsgi_cgi_manage_options,
.request = uwsgi_cgi_request,
+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
+5 -2
View File
@@ -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);
+175 -8
View File
@@ -21,6 +21,8 @@
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT 150007
#define LONG_ARGS_FASTROUTER_USE_CODE_STRING 150008
#define LONG_ARGS_FASTROUTER_TOLERANCE 150009
#define LONG_ARGS_FASTROUTER_STATS 150010
#define LONG_ARGS_FASTROUTER_ZERG 150011
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
@@ -33,9 +35,12 @@
#define del_check_timeout(x) rb_erase(&x->rbt, ufr.timeouts);
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
void fastrouter_send_stats(int);
struct uwsgi_fastrouter_socket {
char *name;
int fd;
char *zerg;
struct uwsgi_fastrouter_socket *next;
};
@@ -56,6 +61,8 @@ struct uwsgi_fastrouter {
char *base;
int base_len;
char *stats_server;
char *subscription_server;
struct uwsgi_subscribe_slot *subscriptions;
int subscription_regexp;
@@ -88,7 +95,7 @@ static void fastrouter_go_cheap(void) {
}
static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name, int fd) {
struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets, *old_uwsgi_sock;
@@ -108,6 +115,12 @@ static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
memset(uwsgi_sock, 0, sizeof(struct uwsgi_fastrouter_socket));
uwsgi_sock->name = name;
if (name) {
uwsgi_sock->fd = -1;
}
else {
uwsgi_sock->fd = fd;
}
return uwsgi_sock;
}
@@ -116,6 +129,7 @@ static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
struct option fastrouter_options[] = {
{"fastrouter", required_argument, 0, LONG_ARGS_FASTROUTER},
{"fastrouter-zerg", required_argument, 0, LONG_ARGS_FASTROUTER_ZERG},
{"fastrouter-use-cache", no_argument, &ufr.use_cache, 1},
{"fastrouter-use-pattern", required_argument, 0, LONG_ARGS_FASTROUTER_USE_PATTERN},
{"fastrouter-use-base", required_argument, 0, LONG_ARGS_FASTROUTER_USE_BASE},
@@ -126,6 +140,9 @@ struct option fastrouter_options[] = {
{"fastrouter-subscription-slot", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT},
{"fastrouter-subscription-use-regexp", no_argument, &ufr.subscription_regexp, 1},
{"fastrouter-timeout", required_argument, 0, LONG_ARGS_FASTROUTER_TIMEOUT},
{"fastrouter-stats", required_argument, 0, LONG_ARGS_FASTROUTER_STATS},
{"fastrouter-stats-server", required_argument, 0, LONG_ARGS_FASTROUTER_STATS},
{"fastrouter-ss", required_argument, 0, LONG_ARGS_FASTROUTER_STATS},
{0, 0, 0, 0},
};
@@ -143,10 +160,15 @@ void fastrouter_manage_subscription(char *key, uint16_t keylen, char *val, uint1
usr->address = val;
usr->address_len = vallen;
}
else if (!uwsgi_strncmp("modifier1", 9, key, keylen)) {
usr->modifier1 = uwsgi_str_num(val, vallen);
}
else if (!uwsgi_strncmp("cores", 5, key, keylen)) {
usr->cores = uwsgi_str_num(val, vallen);
}
else if (!uwsgi_strncmp("load", 4, key, keylen)) {
usr->load = uwsgi_str_num(val, vallen);
}
}
struct fastrouter_session {
@@ -181,7 +203,7 @@ static void close_session(struct fastrouter_session **fr_table, struct fastroute
close(fr_session->fd);
fr_table[fr_session->fd] = NULL;
if (fr_session->instance_fd != -1) {
if (ufr.subscriptions && fr_session->un && fr_session->un->len > 0) {
// decrease reference count
#ifdef UWSGI_DEBUG
@@ -194,6 +216,7 @@ static void close_session(struct fastrouter_session **fr_table, struct fastroute
if (fr_session->instance_failed || fr_session->status == FASTROUTER_STATUS_CONNECTING) {
if (fr_session->un->death_mark == 0)
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (int) fr_session->hostname_len, fr_session->hostname, (int) fr_session->instance_address_len,fr_session->instance_address);
fr_session->un->failcnt++;
fr_session->un->death_mark = 1;
// check if i can remove the node
if (fr_session->un->reference == 0) {
@@ -205,6 +228,8 @@ static void close_session(struct fastrouter_session **fr_table, struct fastroute
}
}
if (fr_session->instance_fd != -1) {
close(fr_session->instance_fd);
fr_table[fr_session->instance_fd] = NULL;
}
@@ -308,6 +333,7 @@ void fastrouter_loop() {
socklen_t solen = sizeof(int);
int ufr_subserver = -1;
int ufr_stats_server = -1;
for(i=0;i<2048;i++) {
fr_table[i] = NULL;
@@ -318,7 +344,10 @@ void fastrouter_loop() {
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
if (ufr_sock->name[0] == '=') {
if (ufr_sock->fd > -1) {
ufr_sock->name = uwsgi_getsockname(ufr_sock->fd);
}
else if (ufr_sock->name[0] == '=') {
int shared_socket = atoi(ufr_sock->name+1);
if (shared_socket >= 0) {
ufr_sock->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
@@ -337,7 +366,12 @@ void fastrouter_loop() {
}
}
uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);
if (ufr_sock->zerg) {
uwsgi_log("uwsgi fastrouter/proxy bound on %s (from zerg server %s)\n", ufr_sock->name, ufr_sock->zerg);
}
else {
uwsgi_log("uwsgi fastrouter/proxy bound on %s\n", ufr_sock->name);
}
if (!ufr.cheap) {
event_queue_add_fd_read(ufr.queue, ufr_sock->fd);
@@ -364,6 +398,23 @@ void fastrouter_loop() {
//ufr.subscriptions_check = add_check_timeout(10);
}
if (ufr.stats_server) {
char *tcp_port = strchr(ufr.stats_server, ':');
if (tcp_port) {
// disable deferred accept for this socket
int current_defer_accept = uwsgi.no_defer_accept;
uwsgi.no_defer_accept = 1;
ufr_stats_server = bind_to_tcp(ufr.stats_server, uwsgi.listen_queue, tcp_port);
uwsgi.no_defer_accept = current_defer_accept;
}
else {
ufr_stats_server = bind_to_unix(ufr.stats_server, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
event_queue_add_fd_read(ufr.queue, ufr_stats_server);
uwsgi_log("*** FastRouter stats server enabled on %s fd: %d ***\n", ufr.stats_server, ufr_stats_server);
}
if (ufr.pattern) {
init_magic_table(magic_table);
}
@@ -430,7 +481,10 @@ void fastrouter_loop() {
continue;
}
if (interesting_fd == ufr_subserver) {
if (interesting_fd == ufr_stats_server) {
fastrouter_send_stats(ufr_stats_server);
}
else if (interesting_fd == ufr_subserver) {
len = recv(ufr_subserver, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(ufr.queue, ufr_subserver);
@@ -456,6 +510,7 @@ void fastrouter_loop() {
if (node && node->len) {
if (node->death_mark == 0)
uwsgi_log("[uwsgi-fastrouter] %.*s => marking %.*s as failed\n", (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) {
@@ -486,7 +541,8 @@ void fastrouter_loop() {
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) {
uwsgi_error("recv()");
if (len < 0)
uwsgi_error("recv()");
close_session(fr_table, fr_session);
break;
}
@@ -755,14 +811,39 @@ int fastrouter_opt(int i, char *optarg) {
char *cs;
char *cs_code;
char *cs_func;
int zerg_fd;
int *zerg;
int j;
struct uwsgi_fastrouter_socket *fr_sock;
switch(i) {
case LONG_ARGS_FASTROUTER:
uwsgi_fastrouter_new_socket(generate_socket_name(optarg));
uwsgi_fastrouter_new_socket(generate_socket_name(optarg), -1);
return 1;
case LONG_ARGS_FASTROUTER_ZERG:
zerg_fd = uwsgi_connect(optarg, 30, 0);
if (zerg_fd < 0) {
uwsgi_log("--- unable to connect to zerg server ---\n");
exit(1);
}
zerg = uwsgi_attach_fd(zerg_fd, 8, "uwsgi-zerg", 11);
if (zerg == NULL) {
uwsgi_log("--- invalid data received from zerg-server ---\n");
exit(1);
}
close(zerg_fd);
for(j=0;j<8;j++) {
if (zerg[j] == -1) break;
fr_sock = uwsgi_fastrouter_new_socket(NULL, zerg[j]);
fr_sock->zerg = optarg;
}
return 1;
case LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER:
ufr.subscription_server = optarg;
return 1;
case LONG_ARGS_FASTROUTER_STATS:
ufr.stats_server = optarg;
return 1;
case LONG_ARGS_FASTROUTER_EVENTS:
ufr.nevents = atoi(optarg);
return 1;
@@ -813,3 +894,89 @@ struct uwsgi_plugin fastrouter_plugin = {
.init = fastrouter_init,
};
#define stats_send_llu(x, y) fprintf(output, x, (long long unsigned int) y)
#define stats_send(x, y) fprintf(output, x, y)
void fastrouter_send_stats(int fd) {
struct sockaddr_un client_src;
socklen_t client_src_len = 0;
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
if (client_fd < 0) {
uwsgi_error("accept()");
return;
}
FILE *output = fdopen(client_fd, "w");
if (!output) {
uwsgi_error("fdopen()");
close(client_fd);
return;
}
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()));
char *cwd = uwsgi_get_cwd();
stats_send("\"cwd\": \"%s\",\n", cwd);
free(cwd);
fprintf(output, "\"fastrouter\": [");
struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets;
while(uwsgi_sock) {
if (uwsgi_sock->next) {
stats_send("\"%s\",", uwsgi_sock->name);
}
else {
stats_send("\"%s\"", uwsgi_sock->name);
}
uwsgi_sock = uwsgi_sock->next;
}
fprintf(output, "],\n");
if (ufr.subscription_server) {
fprintf(output, "\"subscriptions\": [\n");
struct uwsgi_subscribe_slot *s_slot = ufr.subscriptions;
while(s_slot) {
fprintf(output, "\t{ \"key\": \"%.*s\",\n", s_slot->keylen, s_slot->key);
fprintf(output, "\t\t\"hits\": %llu,\n", (unsigned long long) s_slot->hits);
fprintf(output, "\t\t\"nodes\": [\n");
struct uwsgi_subscribe_node *s_node = s_slot->nodes;
while(s_node) {
fprintf(output, "\t\t\t{\"name\": \"%.*s\", \"modifier1\": %d, \"modifier2\": %d, \"last_check\": %llu, \"requests\": %llu, \"tx\": %llu, \"cores\": %llu, \"load\": %llu, \"ref\": %llu, \"failcnt\": %llu, \"death_mark\": %d}", s_node->len, s_node->name, s_node->modifier1, s_node->modifier2,
(unsigned long long) s_node->last_check, (unsigned long long) s_node->requests, (unsigned long long) s_node->transferred,
(unsigned long long) s_node->cores, (unsigned long long) s_node->load, (unsigned long long) s_node->reference,
(unsigned long long) s_node->failcnt, s_node->death_mark);
if (s_node->next) {
fprintf(output, ",\n");
}
else {
fprintf(output, "\n");
}
s_node = s_node->next;
}
fprintf(output, "\t\t]\n");
if (s_slot->next) {
fprintf(output, "\t},\n");
}
else {
fprintf(output, "\t}\n");
}
s_slot = s_slot->next;
// check for loopy optimization
if (s_slot == ufr.subscriptions) break;
}
fprintf(output, "],\n");
}
fprintf(output,"\"cheap\": %d\n", ufr.i_am_cheap);
fprintf(output,"}\n");
fclose(output);
}
+1 -2
View File
@@ -58,14 +58,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
+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':
+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']
+2 -1
View File
@@ -584,7 +584,8 @@ void http_loop() {
event_queue_add_fd_read(uhttp_queue, uhttp_session->fd);
#endif
if (len <= 0) {
uwsgi_error("recv()");
if (len < 0)
uwsgi_error("recv()");
close_session(uhttp_table, uhttp_session);
break;
}
+78
View File
@@ -0,0 +1,78 @@
#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);
}
int uwsgi_logsocket_init() {
return 0;
}
struct uwsgi_plugin logsocket_plugin = {
.name = "logsocket",
.on_load = uwsgi_logsocket_register,
.init = uwsgi_logsocket_init
};
+6
View File
@@ -0,0 +1,6 @@
NAME='logsocket'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['logsocket_plugin']
+2 -2
View File
@@ -682,7 +682,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 +698,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) {
+16
View File
@@ -0,0 +1,16 @@
PHP_ARG_WITH(uwsgi,,
[ --with-uwsgi=UWSGISRCDIR Build PHP as a uWSGI plugin (UNIX/POSIX only)], no, no)
AC_MSG_CHECKING([for UWSGI])
if test "$PHP_UWSGI" != "no"; then
INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED $PHP_UWSGI/php_plugin.so"
UWSGI_CFLAGS=`cd $PHP_UWSGI ; python uwsgiconfig.py --cflags`
UWSGI_CFLAGS="$UWSGI_CFLAGS -I$PHP_UWSGI"
PHP_SELECT_SAPI(uwsgi, shared, php_plugin.c, $UWSGI_CFLAGS)
AC_MSG_RESULT([$PHP_UWSGI])
else
AC_MSG_RESULT(no)
fi
+494
View File
@@ -0,0 +1,494 @@
#include "php.h"
#include "SAPI.h"
#include "php_main.h"
#include "php_variables.h"
#include "ext/standard/php_smart_str.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
// http status codes list
extern struct http_status_codes hsc[];
struct uwsgi_php {
struct uwsgi_string_list *allowed_docroot;
struct uwsgi_string_list *allowed_ext;
} uphp;
#define LONG_ARGS_PHP_BASE 17000 + ((14 + 1) * 1000)
#define LONG_ARGS_PHP_INI LONG_ARGS_PHP_BASE + 1
#define LONG_ARGS_PHP_ALLOWED_DOCROOT LONG_ARGS_PHP_BASE + 2
#define LONG_ARGS_PHP_ALLOWED_EXT LONG_ARGS_PHP_BASE + 3
struct option uwsgi_php_options[] = {
{"php-ini", required_argument, 0, LONG_ARGS_PHP_INI},
{"php-config", required_argument, 0, LONG_ARGS_PHP_INI},
{"php-allowed-docroot", required_argument, 0, LONG_ARGS_PHP_ALLOWED_DOCROOT},
{"php-allowed-ext", required_argument, 0, LONG_ARGS_PHP_ALLOWED_EXT},
{0, 0, 0, 0},
};
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 != 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\n\r\nNot Found", 35);
}
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\n\r\nForbidden", 35);
}
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;
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;
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);
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);
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);
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);
}
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;
static int php_uwsgi_startup(sapi_module_struct *sapi_module)
{
if (php_module_startup(&uwsgi_sapi_module, NULL, 0)==FAILURE) {
return FAILURE;
} else {
return SUCCESS;
}
}
static void sapi_uwsgi_log_message(char *message) {
uwsgi_log(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;
sapi_startup(&uwsgi_sapi_module);
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 (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];
uint16_t docroot_len = 0;
char *path_info = NULL;
size_t real_filename_len = 0;
zend_file_handle file_handle;
SG(server_context) = (void *) wsgi_req;
if (uwsgi_parse_vars(wsgi_req)) {
return -1;
}
char *docroot = uwsgi_get_var(wsgi_req, (char *) "DOCUMENT_ROOT", 13, &docroot_len);
if (!docroot) {
docroot = uwsgi.cwd;
docroot_len = strlen(uwsgi.cwd);
}
char *filename = uwsgi_concat4n(docroot, docroot_len, "/", 1, wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
if (uwsgi_php_walk(wsgi_req, filename, docroot, docroot_len, &path_info)) {
free(filename);
return -1;
}
if (path_info) {
wsgi_req->path_info = path_info;
wsgi_req->path_info_len = strlen(wsgi_req->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 (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 (docroot[docroot_len-1] == '/') {
wsgi_req->script_name = real_filename + (docroot_len-1);
}
else {
wsgi_req->script_name = real_filename + docroot_len;
}
wsgi_req->script_name_len = strlen(wsgi_req->script_name);
#ifdef UWSGI_DEBUG
uwsgi_log("php filename = %s\n", real_filename);
#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);
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);
}
int uwsgi_php_manage_options(int i, char *optarg) {
switch(i) {
case LONG_ARGS_PHP_INI:
uwsgi_sapi_module.php_ini_path_override = uwsgi_str(optarg);
uwsgi_sapi_module.php_ini_ignore = 1;
return 1;
case LONG_ARGS_PHP_ALLOWED_DOCROOT:
uwsgi_string_new_list(&uphp.allowed_docroot, optarg);
return 1;
case LONG_ARGS_PHP_ALLOWED_EXT:
uwsgi_string_new_list(&uphp.allowed_ext, optarg);
return 1;
}
return 0;
}
SAPI_API struct uwsgi_plugin php_plugin = {
.modifier1 = 14,
.init = uwsgi_php_init,
.request = uwsgi_php_request,
.after_request = uwsgi_php_after_request,
.options = uwsgi_php_options,
.manage_opt = uwsgi_php_manage_options,
};
+1 -1
View File
@@ -87,7 +87,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);
}
}
+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;
}
+8 -6
View File
@@ -155,26 +155,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);
}
+35 -21
View File
@@ -80,9 +80,7 @@ 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;
@@ -320,9 +318,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 +368,25 @@ 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++;
if (app_type == PYTHON_APP_TYPE_WSGI) {
uwsgi_log( "WSGI application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
}
else if (app_type == PYTHON_APP_TYPE_WEB3) {
uwsgi_log( "Web3 application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
}
else if (app_type == PYTHON_APP_TYPE_PUMP) {
uwsgi_log( "Pump application %d (mountpoint='%.*s') ready on interpreter %p pid: %d%s\n", id, wi->mountpoint_len, wi->mountpoint, wi->interpreter, (int) getpid(), default_app);
}
uwsgi_rawlog("\n");
uwsgi_apps_cnt++;
if (multiapp > 1) {
for(i=1;i<multiapp;i++) {
@@ -540,6 +539,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(1);
}
else if (!strcmp(what+strlen(what)-4, ".ini")) {
callable = uwsgi_paste_loader((void *)what);
@@ -606,30 +606,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;
}
+50 -18
View File
@@ -29,6 +29,10 @@ struct option uwsgi_python_options[] = {
{"pyimport", required_argument, 0, LONG_ARGS_PYIMPORT},
{"py-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"python-import", required_argument, 0, LONG_ARGS_PYIMPORT},
{"shared-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
{"shared-pyimport", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
{"shared-py-import", required_argument, 0, LONG_ARGS_SHARED_PYIMPORT},
{"shared-python-import", required_argument, 0, LONG_ARGS_SHARED_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},
@@ -739,6 +743,9 @@ int uwsgi_python_manage_options(int i, char *optarg) {
uwsgi.honour_stdin = 1;
up.pyshell = 1;
return 1;
case LONG_ARGS_SHARED_PYIMPORT:
uwsgi_string_new_list(&up.shared_import_list, optarg);
return 1;
case LONG_ARGS_PYIMPORT:
uwsgi_string_new_list(&up.import_list, optarg);
return 1;
@@ -892,17 +899,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();
@@ -912,7 +910,6 @@ void uwsgi_python_init_apps() {
#endif
#endif
#ifdef __linux__
#ifndef UWSGI_PYPY
#ifdef UWSGI_EMBEDDED
@@ -930,6 +927,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;
@@ -1072,6 +1097,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;
@@ -1266,36 +1294,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())
@@ -1479,6 +1509,8 @@ struct uwsgi_plugin python_plugin = {
.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,
+52 -127
View File
@@ -148,24 +148,14 @@ char *uwsgi_encode_pydict(PyObject * pydict, uint16_t * size) {
keysize = PyString_Size(key);
valsize = PyString_Size(val);
if (bufptr + keysize + 2 + valsize + 2 <= buf + *size) {
#ifdef __BIG_ENDIAN__
keysize = uwsgi_swap16(keysize);
#endif
memcpy(bufptr, &keysize, 2);
bufptr += 2;
#ifdef __BIG_ENDIAN__
keysize = uwsgi_swap16(keysize);
#endif
*bufptr++ = (uint8_t) (keysize & 0xff);
*bufptr++ = (uint8_t) ((keysize >> 8) & 0xff);
memcpy(bufptr, PyString_AsString(key), keysize);
bufptr += keysize;
#ifdef __BIG_ENDIAN__
valsize = uwsgi_swap16(valsize);
#endif
memcpy(bufptr, &valsize, 2);
bufptr += 2;
#ifdef __BIG_ENDIAN__
valsize = uwsgi_swap16(valsize);
#endif
*bufptr++ = (uint8_t) (valsize & 0xff);
*bufptr++ = (uint8_t) ((valsize >> 8) & 0xff);
memcpy(bufptr, PyString_AsString(val), valsize);
bufptr += valsize;
}
@@ -294,13 +284,13 @@ PyObject *py_uwsgi_add_file_monitor(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
char buffer[0xffff];
char *func;
uint16_t size = 0;
PyObject *py_func;
int argc = PyTuple_Size(args);
int i;
char *argv[0xff];
char *argv[256];
uint16_t argvs[256];
// TODO better error reporting
if (argc < 1)
@@ -314,19 +304,29 @@ PyObject *py_uwsgi_call(PyObject * self, PyObject * args) {
func = PyString_AsString(py_func);
for (i = 0; i < (argc - 1); i++) {
argv[i] = PyString_AsString(PyTuple_GetItem(args, i + 1));
PyObject *py_str = PyTuple_GetItem(args, i + 1);
if (!PyString_Check(py_str)) {
goto clear;
}
argv[i] = PyString_AsString(py_str);
argvs[i] = PyString_Size(py_str);
}
size = uwsgi_rpc(func, argc - 1, argv, buffer);
char *response = uwsgi_do_rpc(NULL, func, argc - 1, argv, argvs, &size);
if (size > 0) {
return PyString_FromStringAndSize(buffer, size);
PyObject *ret = PyString_FromStringAndSize(response, size);
free(response);
return ret;
}
clear:
Py_INCREF(Py_None);
return Py_None;
clear:
return PyErr_Format(PyExc_ValueError, "unable to call rpc function");
}
PyObject *py_uwsgi_rpc_list(PyObject * self, PyObject * args) {
@@ -346,19 +346,15 @@ PyObject *py_uwsgi_rpc_list(PyObject * self, PyObject * args) {
PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
char buffer[0xffff];
char *node, *func;
char *node = NULL, *func;
uint16_t size = 0;
PyObject *py_node, *py_func;
struct wsgi_request rpc_req;
int argc = PyTuple_Size(args);
char *argv[0xff];
int i, fd;
uint16_t pktsize = 0, ulen;
char *bufptr;
int rlen;
int rpc_args = 0;
int argc = PyTuple_Size(args);
char *argv[256];
uint16_t argvs[256];
int i;
// TODO better error reporting
if (argc < 2)
@@ -369,9 +365,6 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
if (PyString_Check(py_node)) {
node = PyString_AsString(py_node);
}
else {
node = "";
}
py_func = PyTuple_GetItem(args, 1);
@@ -381,87 +374,28 @@ PyObject *py_uwsgi_rpc(PyObject * self, PyObject * args) {
func = PyString_AsString(py_func);
for (i = 0; i < (argc - 2); i++) {
argv[i] = PyString_AsString(PyTuple_GetItem(args, i + 2));
rpc_args++;
PyObject *py_str = PyTuple_GetItem(args, i + 2);
if (!PyString_Check(py_str))
goto clear;
argv[i] = PyString_AsString(py_str);
argvs[i] = PyString_Size(py_str);
}
if (!strcmp(node, "")) {
if (!rpc_args) {
size = uwsgi_rpc(func, 0, NULL, buffer);
}
else {
size = uwsgi_rpc(func, rpc_args, argv, buffer);
}
}
else {
// connect to node
fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0)
goto clear;
// prepare a uwsgi array
pktsize = 2 + strlen(func);
for (i = 0; i < argc - 2; i++) {
pktsize += 2 + strlen(argv[i]);
}
memset(&rpc_req, 0, sizeof(struct wsgi_request));
rpc_req.uh.modifier1 = 173;
rpc_req.uh.pktsize = pktsize;
rpc_req.uh.modifier2 = 0;
bufptr = buffer;
ulen = strlen(func);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, func, ulen);
bufptr += ulen;
for (i = 0; i < argc - 2; i++) {
ulen = strlen(argv[i]);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, argv[i], ulen);
bufptr += ulen;
}
if (write(fd, &rpc_req.uh, 4) != 4) {
uwsgi_error("write()");
close(fd);
goto clear;
}
if (write(fd, buffer, pktsize) != pktsize) {
uwsgi_error("write()");
close(fd);
goto clear;
}
rlen = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
if (rlen > 0) {
rpc_req.poll.fd = fd;
rpc_req.poll.events = POLLIN;
rpc_req.buffer = buffer;
if (uwsgi_parse_packet(&rpc_req, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT])) {
size = rpc_req.uh.pktsize;
}
}
}
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
if (size > 0) {
return PyString_FromStringAndSize(buffer, size);
}
PyObject *ret = PyString_FromStringAndSize(response, size);
free(response);
return ret;
}
Py_INCREF(Py_None);
return Py_None;
clear:
Py_INCREF(Py_None);
return Py_None;
return PyErr_Format(PyExc_ValueError, "unable to call rpc function");
}
PyObject *py_uwsgi_register_rpc(PyObject * self, PyObject * args) {
@@ -1656,24 +1590,15 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
valsize = PyString_Size(val);
if (cur_buf + keysize + 2 + valsize + 2 <= spool_buffer + UMAX16) {
#ifdef __BIG_ENDIAN__
keysize = uwsgi_swap16(keysize);
#endif
memcpy(cur_buf, &keysize, 2);
cur_buf += 2;
#ifdef __BIG_ENDIAN__
keysize = uwsgi_swap16(keysize);
#endif
*cur_buf++ = (uint8_t) (keysize & 0xff);
*cur_buf++ = (uint8_t) ((keysize >> 8) & 0xff);
memcpy(cur_buf, PyString_AsString(key), keysize);
cur_buf += keysize;
#ifdef __BIG_ENDIAN__
valsize = uwsgi_swap16(valsize);
#endif
memcpy(cur_buf, &valsize, 2);
cur_buf += 2;
#ifdef __BIG_ENDIAN__
valsize = uwsgi_swap16(valsize);
#endif
*cur_buf++ = (uint8_t) (valsize & 0xff);
*cur_buf++ = (uint8_t) ((valsize >> 8) & 0xff);
memcpy(cur_buf, PyString_AsString(val), valsize);
cur_buf += valsize;
}
@@ -2345,7 +2270,7 @@ PyObject *py_uwsgi_route(PyObject * self, PyObject * args) {
ui->func = NULL;
// mark a route request
wsgi_req->status = -1;
wsgi_req->status = -17;
return (PyObject *) ui;
}
+4 -2
View File
@@ -21,6 +21,7 @@
#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 LONG_ARGS_SHARED_PYIMPORT LONG_ARGS_PYTHON_BASE + 14
#define PYTHON_APP_TYPE_WSGI 0
#define PYTHON_APP_TYPE_WEB3 1
@@ -133,6 +134,7 @@ struct uwsgi_python {
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;
@@ -210,8 +212,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 +259,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 *);
+20
View File
@@ -599,3 +599,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
}
}
+197
View File
@@ -25,6 +25,26 @@ VALUE rack_uwsgi_warning(VALUE *class, VALUE rbmessage) {
return Qnil;
}
VALUE rack_uwsgi_log(VALUE *class, VALUE msg) {
Check_Type(msg, T_STRING);
uwsgi_log("%s\n", RSTRING_PTR(msg));
return Qnil;
}
VALUE rack_uwsgi_i_am_the_spooler(VALUE *class) {
#ifdef UWSGI_SPOOLER
if (uwsgi.mypid == uwsgi.shared->spooler_pid) {
return Qtrue;
}
#endif
return Qfalse;
}
VALUE rack_uwsgi_setprocname(VALUE *class, VALUE rbname) {
@@ -595,6 +615,59 @@ VALUE uwsgi_ruby_signal_registered(VALUE *class, VALUE signum) {
return Qfalse;
}
VALUE uwsgi_ruby_do_rpc(int argc, VALUE *rpc_argv, VALUE *class) {
char *node = NULL, *func;
uint16_t size = 0;
char *argv[256];
uint16_t argvs[256];
int i;
// TODO better error reporting
if (argc < 2)
goto clear;
VALUE rpc_node = rpc_argv[0];
if (TYPE(rpc_node) == T_STRING) {
node = RSTRING_PTR(rpc_node);
}
VALUE rpc_func = rpc_argv[1];
if (TYPE(rpc_func) != T_STRING)
goto clear;
func = RSTRING_PTR(rpc_func);
for (i = 0; i < (argc - 2); i++) {
VALUE rpc_str = rpc_argv[i + 2];
if (TYPE(rpc_str) != T_STRING)
goto clear;
argv[i] = RSTRING_PTR(rpc_str);
argvs[i] = RSTRING_LEN(rpc_str);
}
char *response = uwsgi_do_rpc(node, func, argc - 2, argv, argvs, &size);
if (size > 0) {
VALUE ret = rb_str_new(response, size);
free(response);
return ret;
}
clear:
rb_raise(rb_eRuntimeError, "unable to call rpc function");
return Qnil;
}
VALUE uwsgi_ruby_register_rpc(int argc, VALUE *argv, VALUE *class) {
int rb_argc = 0;
@@ -674,6 +747,118 @@ VALUE uwsgi_ruby_signal(int argc, VALUE *argv, VALUE *class) {
return Qtrue;
}
int rack_uwsgi_build_spool(VALUE rbkey, VALUE rbval, VALUE argv) {
char **sa = (char **) argv;
char *cur_buf = sa[0];
char *watermark = sa[1];
if (TYPE(rbkey) != T_STRING || TYPE(rbval) != T_STRING) {
rb_raise(rb_eRuntimeError, "spool hash must contains only strings");
return ST_STOP;
}
char *key = RSTRING_PTR(rbkey); uint16_t keylen = RSTRING_LEN(rbkey);
char *val = RSTRING_PTR(rbval); uint16_t vallen = RSTRING_LEN(rbval);
if (cur_buf + (2+keylen+2+vallen) > watermark) {
rb_raise(rb_eRuntimeError, "spool hash size can be no more than 64K");
return ST_STOP;
}
*cur_buf++ = (uint8_t) (keylen & 0xff);
*cur_buf++ = (uint8_t) ((keylen >> 8) & 0xff);
memcpy(cur_buf, key, keylen); cur_buf += keylen;
*cur_buf++ = (uint8_t) (vallen & 0xff);
*cur_buf++ = (uint8_t) ((vallen >> 8) & 0xff);
memcpy(cur_buf, val, vallen); cur_buf += vallen;
// fix the ptr
sa[0] = cur_buf;
return ST_CONTINUE;
}
VALUE rack_uwsgi_send_spool(VALUE *class, VALUE args) {
char spool_filename[1024];
struct wsgi_request *wsgi_req = current_wsgi_req();
char *priority = NULL;
long numprio = 0;
time_t at = 0;
char *body = NULL;
size_t body_len= 0;
Check_Type(args, T_HASH);
// priority
#ifdef RUBY19
VALUE rbprio = rb_hash_lookup(args, rb_str_new2("priority"));
#else
VALUE rbprio = rb_hash_aref(args, rb_str_new2("priority"));
#endif
if (TYPE(rbprio) == T_FIXNUM) {
numprio = NUM2INT(rbprio);
rb_hash_delete(args, rb_str_new2("priority"));
}
// at
#ifdef RUBY19
VALUE rbat = rb_hash_lookup(args, rb_str_new2("at"));
#else
VALUE rbat = rb_hash_aref(args, rb_str_new2("at"));
#endif
if (TYPE(rbat) == T_FIXNUM) {
at = NUM2INT(rbat);
rb_hash_delete(args, rb_str_new2("at"));
}
// body
#ifdef RUBY19
VALUE rbbody = rb_hash_lookup(args, rb_str_new2("body"));
#else
VALUE rbbody = rb_hash_aref(args, rb_str_new2("body"));
#endif
if (TYPE(rbbody) == T_STRING) {
body = RSTRING_PTR(rbbody);
body_len = RSTRING_LEN(rbbody);
rb_hash_delete(args, rb_str_new2("body"));
}
char *spool_buffer = uwsgi_malloc(UMAX16);
char *argv[2];
argv[0] = spool_buffer;
argv[1] = spool_buffer + UMAX16 ;
rb_hash_foreach(args, rack_uwsgi_build_spool, (VALUE) argv);
if (numprio) {
priority = uwsgi_num2str(numprio);
}
int ret = spool_request(spool_filename, uwsgi.workers[0].requests + 1, wsgi_req->async_id, spool_buffer, argv[0] - spool_buffer, priority, at, body, body_len);
if (priority) {
free(priority);
}
free(spool_buffer);
if (ret > 0) {
char *slash = uwsgi_get_last_char(spool_filename, '/');
if (slash) {
return rb_str_new2(slash+1);
}
return rb_str_new2(spool_filename);
}
rb_raise(rb_eRuntimeError, "unable to spool job");
return Qnil;
}
void uwsgi_rack_init_api() {
@@ -708,10 +893,18 @@ void uwsgi_rack_init_api() {
uwsgi_rack_api("request_id", rack_uwsgi_request_id, 0);
uwsgi_rack_api("worker_id", rack_uwsgi_worker_id, 0);
uwsgi_rack_api("mule_id", rack_uwsgi_mule_id, 0);
uwsgi_rack_api("i_am_the_spooler", rack_uwsgi_i_am_the_spooler, 0);
uwsgi_rack_api("send_to_spooler", rack_uwsgi_send_spool, 1);
uwsgi_rack_api("spool", rack_uwsgi_send_spool, 1);
uwsgi_rack_api("log", rack_uwsgi_log, 1);
uwsgi_rack_api("logsize", rack_uwsgi_logsize, 0);
uwsgi_rack_api("set_warning_message", rack_uwsgi_warning, 1);
uwsgi_rack_api("rpc", uwsgi_ruby_do_rpc, -1);
if (uwsgi.cache_max_items > 0) {
@@ -765,6 +958,10 @@ void uwsgi_rack_init_api() {
rb_const_set(rb_uwsgi_embedded, rb_intern("OPT"), uwsgi_rb_opt_hash);
rb_const_set(rb_uwsgi_embedded, rb_intern("SPOOL_OK"), INT2NUM(-2));
rb_const_set(rb_uwsgi_embedded, rb_intern("SPOOL_IGNORE"), INT2NUM(0));
rb_const_set(rb_uwsgi_embedded, rb_intern("SPOOL_RETRY"), INT2NUM(-1));
rb_const_set(rb_uwsgi_embedded, rb_intern("VERSION"), rb_str_new2(UWSGI_VERSION));
rb_const_set(rb_uwsgi_embedded, rb_intern("HOSTNAME"), rb_str_new(uwsgi.hostname, uwsgi.hostname_len));
if (uwsgi.pidfile) {
+163 -84
View File
@@ -66,7 +66,7 @@ VALUE rb_uwsgi_io_gets(VALUE obj, VALUE args) {
// return the whole body as string
uwsgi_log("rack.input gets is not implemented (req %p)\n", wsgi_req);
rb_raise(rb_eRuntimeError, "rack.input::gets is not implemented (req %p)\n", wsgi_req);
return Qnil;
}
@@ -76,7 +76,7 @@ VALUE rb_uwsgi_io_each(VALUE obj, VALUE args) {
Data_Get_Struct(obj, struct wsgi_request, wsgi_req);
// yield strings chunks
uwsgi_log("rack.input each is not implemented (req %p)\n", wsgi_req);
rb_raise(rb_eRuntimeError, "rack.input::each is not implemented (req %p)\n", wsgi_req);
return Qnil;
}
@@ -88,7 +88,6 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
VALUE chunk;
int chunk_size;
if (!wsgi_req->post_cl || wsgi_req->buf_pos >= wsgi_req->post_cl) {
return Qnil;
}
@@ -108,8 +107,9 @@ VALUE rb_uwsgi_io_read(VALUE obj, VALUE args) {
wsgi_req->buf_pos+=chunk_size;
return RARRAY_PTR(args)[1];
}
chunk = rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, chunk_size);
wsgi_req->buf_pos+=chunk_size;
return rb_str_new(wsgi_req->post_buffering_buf+wsgi_req->buf_pos, chunk_size);
return chunk;
}
return Qnil;
@@ -149,6 +149,10 @@ VALUE require_rails(VALUE arg) {
#endif
}
VALUE require_thin(VALUE arg) {
return rb_funcall(rb_cObject, rb_intern("require"), 1, rb_str_new2("thin"));
}
VALUE init_rack_app(VALUE);
VALUE rack_call_rpc_handler(VALUE args) {
@@ -157,7 +161,7 @@ VALUE rack_call_rpc_handler(VALUE args) {
}
uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
uint8_t i;
VALUE rb_args = rb_ary_new2(2);
@@ -170,7 +174,7 @@ uint16_t uwsgi_ruby_rpc(void *func, uint8_t argc, char **argv, char *buffer) {
rb_ary_store(rb_args, 0, (VALUE) func);
for (i = 0; i < argc; i++) {
rb_ary_store(rb_rpc_args, i, rb_str_new2(argv[i]));
rb_ary_store(rb_rpc_args, i, rb_str_new(argv[i], argvs[i]));
}
rb_ary_store(rb_args, 1, rb_rpc_args);
@@ -236,6 +240,10 @@ int uwsgi_rack_init(){
return 0;
}
VALUE uwsgi_rb_call_new(VALUE obj) {
return rb_funcall(obj, rb_intern("new"), 0);
}
void uwsgi_rack_init_apps(void) {
int error;
@@ -271,6 +279,10 @@ void uwsgi_rack_init_apps(void) {
exit(1);
}
if (!access("config.ru", R_OK)) {
uwsgi_log("!!! a config.ru file has been found in yor rails app, please use --rack <configfile> instead of the old --rails <app> !!!\n");
}
uwsgi_log("loading rails app %s\n", ur.rails);
rb_protect( require_rails, 0, &error ) ;
if (error) {
@@ -280,13 +292,53 @@ void uwsgi_rack_init_apps(void) {
uwsgi_log("rails app %s ready\n", ur.rails);
VALUE ac = rb_const_get(rb_cObject, rb_intern("ActionController"));
ur.dispatcher = rb_funcall( rb_const_get(ac, rb_intern("Dispatcher")), rb_intern("new"), 0);
ur.dispatcher = Qnil;
if (rb_funcall(ac, rb_intern("const_defined?"), 1, ID2SYM(rb_intern("Dispatcher"))) == Qtrue) {
VALUE ac_dispatcher = rb_const_get(ac, rb_intern("Dispatcher"));
VALUE acd_instance_methods = rb_funcall( ac_dispatcher, rb_intern("instance_methods"), 0);
VALUE acim_call = rb_funcall( acd_instance_methods, rb_intern("include?"), 1, ID2SYM(rb_intern("call")));
if (acim_call == Qfalse) {
acim_call = rb_funcall( acd_instance_methods, rb_intern("include?"), 1, rb_str_new2("call"));
}
if (acim_call == Qtrue) {
ur.dispatcher = rb_protect(uwsgi_rb_call_new, ac_dispatcher, &error);
if (error) {
uwsgi_ruby_exception();
exit(1);
}
}
}
if (ur.dispatcher == Qnil) {
uwsgi_log("non-rack rails version detected...loading thin adapter...\n");
rb_protect( require_thin, 0, &error ) ;
if (error) {
uwsgi_ruby_exception();
exit(1);
}
VALUE thin_rack = rb_const_get(rb_cObject, rb_intern("Rack"));
VALUE thin_rack_adapter = rb_const_get(thin_rack, rb_intern("Adapter"));
VALUE thin_rack_adapter_rails = rb_const_get(thin_rack_adapter, rb_intern("Rails"));
ur.dispatcher = rb_protect( uwsgi_rb_call_new, thin_rack_adapter_rails, &error);
if (error) {
uwsgi_ruby_exception();
exit(1);
}
}
if (ur.dispatcher == Qnil) {
uwsgi_log("unable to load rails dispatcher\n");
exit(1);
}
rb_gc_register_address(&ur.dispatcher);
goto ready;
}
@@ -396,63 +448,50 @@ VALUE send_header(VALUE obj, VALUE headers) {
}
if (TYPE(hkey) != T_STRING || TYPE(hval) != T_STRING) {
goto clear2;
goto clear;
}
//uwsgi_log("header: %.*s: %.*s\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), RSTRING_LEN(hval), RSTRING_PTR(hval));
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
char *header_value = RSTRING_PTR(hval);
int header_value_len = RSTRING_LEN(hval);
size_t header_value_len = RSTRING_LEN(hval);
size_t i,cnt=0;
char *this_header = header_value;
char *header_value_splitted = memchr(header_value, '\n', header_value_len);
for(i=0;i<header_value_len;i++) {
// multiline header, send it !!!
if (header_value[i] == '\n') {
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
if (!header_value_splitted) {
len = wsgi_req->socket->proto_write_header( wsgi_req, header_value, header_value_len);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
wsgi_req->header_cnt++;
//uwsgi_log("(multi) --%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
wsgi_req->header_cnt++;
this_header += cnt+1;
cnt = 0;
continue;
}
cnt++;
}
else {
header_value_splitted[0] = 0;
len = wsgi_req->socket->proto_write_header( wsgi_req, header_value, header_value_splitted-header_value);
if (cnt > 0) {
len = wsgi_req->socket->proto_write_header( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, this_header, cnt);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write_header( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
wsgi_req->header_cnt++;
header_value = header_value_splitted+1;
header_value_len -= header_value_splitted-header_value;
while(header_value_len && (header_value_splitted = memchr(header_value, '\n', header_value_len))) {
header_value_splitted[0] = 0;
len = wsgi_req->socket->proto_write( wsgi_req, RSTRING_PTR(hkey), RSTRING_LEN(hkey));
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write( wsgi_req, (char *)": ", 2);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write( wsgi_req, header_value, header_value_splitted-header_value);
wsgi_req->headers_size += len;
len = wsgi_req->socket->proto_write( wsgi_req, (char *)"\r\n", 2);
wsgi_req->headers_size += len;
wsgi_req->header_cnt++;
header_value = header_value_splitted+1;
header_value_len -= header_value_splitted-header_value;
}
//uwsgi_log("--%.*s: %.*s--\n", RSTRING_LEN(hkey), RSTRING_PTR(hkey), cnt, this_header);
}
clear2:
rb_gc_unregister_address(&hkey);
rb_gc_unregister_address(&hval);
clear:
return Qnil;
@@ -508,6 +547,8 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
) {
rb_hash_aset(env, rb_str_new(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len),
rb_str_new(wsgi_req->hvec[i+1].iov_base, wsgi_req->hvec[i+1].iov_len));
//uwsgi_log("%.*s = %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
}
i++;
}
@@ -549,13 +590,13 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
rb_hash_aset(env, rb_str_new2("rack.errors"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(2), rb_str_new("w",1) ));
ret = rb_protect( call_dispatch, env, &error);
if (error) {
uwsgi_ruby_exception();
//return -1;
goto clear;
}
if (TYPE(ret) == T_ARRAY) {
if (RARRAY_LEN(ret) != 3) {
uwsgi_log("Invalid RACK response size: %d\n", RARRAY_LEN(ret));
@@ -603,8 +644,6 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
rb_protect( iterate_headers, headers, &error);
if (error) {
uwsgi_ruby_exception();
rb_gc_unregister_address(&status);
rb_gc_unregister_address(&headers);
goto clear;
}
}
@@ -615,8 +654,6 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
body = RARRAY_PTR(ret)[2] ;
// TODO protect to_path
if (rb_respond_to( body, rb_intern("to_path") )) {
VALUE sendfile_path = rb_protect( body_to_path, body, &error);
if (error) {
@@ -631,13 +668,19 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
}
}
rb_gc_unregister_address(&sendfile_path);
// we need to close it...
close(wsgi_req->sendfile_fd);
}
}
else if (rb_respond_to( body, rb_intern("each") )) {
rb_protect( iterate_body, body, &error);
if (error) {
uwsgi_ruby_exception();
if (ur.unprotected) {
iterate_body(body);
}
else {
rb_protect( iterate_body, body, &error);
if (error) {
uwsgi_ruby_exception();
}
}
}
@@ -649,14 +692,6 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
}
}
//fine:
/* unregister all the objects created */
rb_gc_unregister_address(&status);
rb_gc_unregister_address(&headers);
rb_gc_unregister_address(&body);
}
else {
internal_server_error(wsgi_req, (char *)"Invalid RACK response");
@@ -664,10 +699,6 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
clear:
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&env);
if (ur.gc_freq <= 1 || ur.cycles%ur.gc_freq == 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("calling ruby GC\n");
@@ -916,26 +947,72 @@ int uwsgi_rack_signal_handler(uint8_t sig, void *handler) {
rb_ary_store(args, 0, rbhandler);
VALUE rbsig = INT2NUM(sig);
rb_ary_store(args, 1, rbsig);
VALUE ret = rb_protect(rack_call_signal_handler, args, &error);
rb_protect(rack_call_signal_handler, args, &error);
if (error) {
uwsgi_ruby_exception();
// free resources (useless ?)
rb_gc_unregister_address(&args);
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&rbsig);
rb_gc();
return -1;
}
// free resources (useless ?)
rb_gc_unregister_address(&args);
rb_gc_unregister_address(&ret);
rb_gc_unregister_address(&rbsig);
rb_gc();
return 0;
}
VALUE uwsgi_rb_do_spooler(VALUE args) {
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
return rb_funcall(uwsgi_rb_embedded, rb_intern("spooler"), 1, args);
}
void uwsgi_ruby_add_item(char *key, uint16_t keylen, char *val, uint16_t vallen, void *data) {
VALUE *spool_dict = (VALUE*) data;
rb_hash_aset(*spool_dict, rb_str_new(key, keylen), rb_str_new(val, vallen));
}
int uwsgi_rack_spooler(char *filename, char *buf, uint16_t len, char *body, size_t body_len) {
int error = 0;
VALUE uwsgi_rb_embedded = rb_const_get(rb_cObject, rb_intern("UWSGI"));
if (!rb_respond_to(uwsgi_rb_embedded, rb_intern("spooler"))) {
rb_gc();
return 0;
}
VALUE spool_dict = rb_hash_new();
if (uwsgi_hooked_parse(buf, len, uwsgi_ruby_add_item, (void *) &spool_dict)) {
rb_gc();
// malformed packet, destroy it
return 0;
}
rb_hash_aset(spool_dict, rb_str_new2("spooler_task_name"), rb_str_new2(filename));
if (body && body_len > 0) {
rb_hash_aset(spool_dict, rb_str_new2("body"), rb_str_new(body, body_len));
}
VALUE ret = rb_protect(uwsgi_rb_do_spooler, spool_dict, &error);
if (error) {
uwsgi_ruby_exception();
rb_gc();
return -1;
}
if (TYPE(ret) == T_FIXNUM) {
rb_gc();
return NUM2INT(ret);
}
// error, retry
rb_gc();
return -1;
}
@@ -954,6 +1031,8 @@ struct uwsgi_plugin rack_plugin = {
.hijack_worker = uwsgi_rack_hijack,
.post_fork = uwsgi_rb_post_fork,
.spooler = uwsgi_rack_spooler,
.init_apps = uwsgi_rack_init_apps,
//.mount_app = uwsgi_rack_mount_app,
.manage_xml = uwsgi_rack_xml,
+3
View File
@@ -10,6 +10,7 @@
#define LONG_ARGS_RUBY_REQUIRE LONG_ARGS_RACK_BASE + 5
#ifndef RUBY19
#include <st.h>
#define rb_errinfo() ruby_errinfo
#define RUBY_GVL_LOCK
#define RUBY_GVL_UNLOCK
@@ -68,6 +69,8 @@ struct uwsgi_rack {
int rb_shell;
int app_id;
int unprotected;
struct uwsgi_string_list *rbrequire;
};
+3 -2
View File
@@ -6,6 +6,7 @@ extern struct uwsgi_server uwsgi;
int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
char *argv[256];
uint16_t argvs[256];
uint8_t argc = 0xff;
/* Standard RPC request */
@@ -24,7 +25,7 @@ int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
uwsgi_log("RPC pktsize %d\n", wsgi_req->uh.pktsize);
#endif
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)) {
uwsgi_log("Invalid RPC request. skip.\n");
return -1;
}
@@ -33,7 +34,7 @@ int uwsgi_rpc_request(struct wsgi_request *wsgi_req) {
uwsgi_log("RPC args %d\n", argc-1);
#endif
wsgi_req->uh.pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, wsgi_req->buffer);
wsgi_req->uh.pktsize = uwsgi_rpc(argv[0], argc-1, argv+1, argvs+1, wsgi_req->buffer);
if (wsgi_req->uh.modifier2 == 0) {
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, (char *)&wsgi_req->uh, 4);
+82
View File
@@ -0,0 +1,82 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
#define MAX_SYSLOG_PKT 1024
ssize_t uwsgi_rsyslog_logger(struct uwsgi_logger *ul, char *message, size_t len) {
char buf[MAX_SYSLOG_PKT];
time_t current_time;
int portn = 514;
int rlen;
if (!ul->configured) {
if (!uwsgi.choosen_logger_arg) {
uwsgi_log_safe("invalid rsyslog 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) {
ul->data = comma+1;
*comma = 0;
}
else {
ul->data = uwsgi_concat2(uwsgi.hostname," uwsgi");
}
char *port = strchr(uwsgi.choosen_logger_arg, ':');
if (port) {
portn = atoi(port+1);
*port = 0;
}
ul->addr_len = socket_to_in_addr(uwsgi.choosen_logger_arg, NULL, portn, &ul->addr.sa_in);
if (port) *port = ':';
if (comma) *comma = ',';
ul->configured = 1;
}
current_time = time(NULL);
// drop newline
if (message[len-1] == '\n') len--;
rlen = snprintf(buf, MAX_SYSLOG_PKT, "<29>%.*s %s: %.*s", 15, ctime(&current_time)+4, (char *) ul->data, (int) len, message);
if (rlen > 0) {
return sendto(ul->fd, buf, rlen, 0, (const struct sockaddr *) &ul->addr, ul->addr_len);
}
return -1;
}
void uwsgi_rsyslog_register() {
uwsgi_register_logger("rsyslog", uwsgi_rsyslog_logger);
}
int uwsgi_rsyslog_init() {
return 0;
}
struct uwsgi_plugin rsyslog_plugin = {
.name = "rsyslog",
.on_load = uwsgi_rsyslog_register,
.init = uwsgi_rsyslog_init
};
+6
View File
@@ -0,0 +1,6 @@
NAME='rsyslog'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['rsyslog_plugin']
+47
View File
@@ -0,0 +1,47 @@
#include "../../uwsgi.h"
#include <syslog.h>
extern struct uwsgi_server uwsgi;
ssize_t uwsgi_syslog_logger(struct uwsgi_logger *ul, char *message, size_t len) {
char *syslog_opts;
if (!ul->configured) {
setlinebuf(stderr);
if (uwsgi.choosen_logger_arg == NULL) {
syslog_opts = "uwsgi";
}
else {
syslog_opts = uwsgi.choosen_logger_arg;
}
openlog(syslog_opts, 0, LOG_DAEMON);
ul->configured = 1;
}
syslog(LOG_INFO, "%.*s", (int) len, message);
return 0;
}
void uwsgi_syslog_register() {
uwsgi_register_logger("syslog", uwsgi_syslog_logger);
}
int uwsgi_syslog_init() {
return 0;
}
struct uwsgi_plugin syslog_plugin = {
.name = "syslog",
.on_load = uwsgi_syslog_register,
.init = uwsgi_syslog_init
};
+6
View File
@@ -0,0 +1,6 @@
NAME='syslog'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['syslog_plugin']
+9 -2
View File
@@ -256,6 +256,7 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
ssize_t remains;
// make this buffer configurable
char post_buf[8192];
char *post_tail = NULL;
// first round ? this memory area will be freed by async_loop
if (!wsgi_req->proto_parser_buf) {
@@ -317,6 +318,10 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
else if (*ptr == '\n' && wsgi_req->proto_parser_status == 3) {
ptr++;
remains = len - (j + 1);
if (remains > 0) {
post_tail = uwsgi_malloc(remains);
memcpy(post_tail, ptr, remains);
}
http_parse(wsgi_req, ptr);
//is there a Content_Length ?
if (wsgi_req->post_cl > 0) {
@@ -328,13 +333,15 @@ int uwsgi_proto_http_parser(struct wsgi_request *wsgi_req) {
}
wsgi_req->proto_parser_pos = 0;
remains = UMIN((size_t) remains, wsgi_req->post_cl);
if (remains) {
if (!fwrite(ptr, remains, 1, wsgi_req->async_post)) {
if (remains && post_tail) {
if (!fwrite(post_tail, remains, 1, wsgi_req->async_post)) {
free(post_tail);
free(wsgi_req->proto_parser_buf);
uwsgi_error("fwrite()");
fclose(wsgi_req->async_post);
return -1;
}
free(post_tail);
wsgi_req->proto_parser_pos += remains;
if (wsgi_req->proto_parser_pos >= wsgi_req->post_cl) {
free(wsgi_req->proto_parser_buf);
+171 -75
View File
@@ -371,7 +371,8 @@ int uwsgi_read_response(int fd, struct uwsgi_header *uh, int timeout, char **buf
}
if (buf && uh->pktsize > 0) {
*buf = uwsgi_malloc(uh->pktsize);
if (*buf == NULL)
*buf = uwsgi_malloc(uh->pktsize);
remains = uh->pktsize;
ptr = *buf;
ret = -1;
@@ -423,9 +424,9 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
}
if (status < 0) {
if (status == -1)
uwsgi_log("error parsing request\n");
uwsgi_log_verbose("error parsing request\n");
else if (status == -2)
uwsgi_log("open-close packet (ping/check) received\n");
uwsgi_log_verbose("open-close packet (ping/check) received\n");
//close(upoll->fd);
return 0;
}
@@ -434,7 +435,7 @@ int uwsgi_parse_packet(struct wsgi_request *wsgi_req, int timeout) {
return 1;
}
int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint16_t argvs[], uint8_t *argc) {
char *ptrbuf, *bufferend;
uint16_t strsize = 0;
@@ -459,6 +460,7 @@ int uwsgi_parse_array(char *buffer, uint16_t size, char **argv, uint8_t *argc) {
if (ptrbuf + strsize <= bufferend) {
// item
argv[*argc] = uwsgi_cheap_string(ptrbuf, strsize);
argvs[*argc] = strsize;
#ifdef UWSGI_DEBUG
uwsgi_log("arg %s\n", argv[*argc]);
#endif
@@ -861,24 +863,40 @@ next:
}
}
// check if a file named uwsgi.check_static+env['PATH_INFO'] exists
if (wsgi_req->path_info_len > 1) {
udd = uwsgi.check_static;
while(udd) {
// need to build the path ?
if (udd->value == NULL) {
udd->value = realpath(udd->key, NULL);
if (!udd->value) goto nextcs;
udd->vallen = strlen(udd->value);
}
// check for static files
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len)) {
return -1;
}
nextcs:
udd = udd->next;
// skip extensions
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
while(sse) {
if (wsgi_req->path_info_len >= sse->len) {
if (!uwsgi_strncmp(wsgi_req->path_info+(wsgi_req->path_info_len - sse->len), sse->len, sse->value, sse->len)) {
return 0;
}
}
sse = sse->next;
}
// check if a file named uwsgi.check_static+env['PATH_INFO'] exists
udd = uwsgi.check_static;
while(udd) {
// need to build the path ?
if (udd->value == NULL) {
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
#endif
udd->value = realpath(udd->key, NULL);
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
#endif
if (!udd->value) goto nextcs;
udd->vallen = strlen(udd->value);
}
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len)) {
return -1;
}
nextcs:
udd = udd->next;
}
// check static-map
@@ -888,7 +906,13 @@ nextcs:
uwsgi_log("checking for %.*s <-> %.*s\n", wsgi_req->path_info_len, wsgi_req->path_info, udd->keylen, udd->key);
#endif
if (udd->status == 0) {
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
#endif
char *real_docroot = realpath(udd->value, NULL);
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
#endif
if (!real_docroot) goto nextsm;
udd->value = real_docroot;
udd->vallen = strlen(udd->value);
@@ -1459,17 +1483,73 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
return NULL;
}
int uwsgi_append_static_path(char *dir, char *file, int file_len) {
size_t len = strlen(dir);
if (len + 1 + file_len > PATH_MAX) {
return -1;
}
if (dir[len-1] == '/') {
memcpy(dir+len, file, file_len);
dir[len+file_len] = 0;
}
else {
dir[len] = '/';
memcpy(dir+len+1, file, file_len);
dir[len+1+file_len] = 0;
}
return len;
}
int uwsgi_static_stat(char *filename, struct stat *st) {
int ret = stat(filename, st);
// if non-existant return -1
if (ret < 0) return -1;
if (S_ISREG(st->st_mode)) return 0;
// check for index
if (S_ISDIR(st->st_mode)) {
struct uwsgi_string_list *usl = uwsgi.static_index;
while(usl) {
ret = uwsgi_append_static_path(filename, usl->value, usl->len);
if (ret >= 0) {
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %s\n", filename);
#endif
if (!uwsgi_static_stat(filename, st)) {
return 0;
}
// reset to original name
filename[ret] = 0;
}
usl = usl->next;
}
}
return -1;
}
int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_t document_root_len, char *path_info, uint16_t path_info_len) {
struct stat st;
char real_filename[PATH_MAX];
struct iovec headers_vec[8];
char real_filename[PATH_MAX+1];
char content_length[sizeof(UMAX64_STR)+1];
size_t real_filename_len = 0;
char *filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
#ifdef UWSGI_DEBUG
uwsgi_log("checking for %s\n", filename);
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
#endif
if (!realpath(filename, real_filename)) {
#ifdef UWSGI_DEBUG
uwsgi_log("unable to get realpath() of the static file\n");
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
#endif
free(filename);
return -1;
@@ -1478,23 +1558,34 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
free(filename);
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
uwsgi_log("security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
return -1;
}
if (!stat(real_filename, &st)) {
if (!uwsgi_static_stat(real_filename, &st)) {
int mime_type_size = 0;
char *mime_type = uwsgi_get_mime_type(path_info, path_info_len, &mime_type_size);
char http_last_modified[49];
real_filename_len = strlen(real_filename);
char *mime_type = uwsgi_get_mime_type(real_filename, real_filename_len, &mime_type_size);
if (wsgi_req->if_modified_since_len) {
time_t ims = parse_http_date(wsgi_req->if_modified_since, wsgi_req->if_modified_since_len);
if (st.st_mtime <= ims) {
wsgi_req->status = 304;
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, " 304 Not Modified\r\n", 19);
headers_vec[0].iov_base = wsgi_req->protocol;
headers_vec[0].iov_len = wsgi_req->protocol_len;
headers_vec[1].iov_base = " 304 Not Modified\r\n";
headers_vec[1].iov_len = 19;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
headers_vec[0].iov_base = ah->value;
headers_vec[0].iov_len = ah->len;
headers_vec[1].iov_base = "\r\n";
headers_vec[1].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
wsgi_req->header_cnt++;
ah = ah->next;
}
@@ -1502,84 +1593,89 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
return 0;
}
}
if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
char http_last_modified[49];
#ifdef UWSGI_DEBUG
uwsgi_log("file %s found\n", real_filename);
uwsgi_log("[uwsgi-fileserve] file %s found\n", real_filename);
#endif
// no need to set content-type/content-length, they will be fixed by the http server/router
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, " 200 OK\r\n", 9);
// HTTP status
headers_vec[0].iov_base = wsgi_req->protocol;
headers_vec[0].iov_len = wsgi_req->protocol_len;
headers_vec[1].iov_base = " 200 OK\r\n";
headers_vec[1].iov_len = 9;
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
// uWSGI additional headers
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
headers_vec[0].iov_base = ah->value;
headers_vec[0].iov_len = ah->len;
headers_vec[1].iov_base = "\r\n";
headers_vec[1].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 2);
wsgi_req->header_cnt++;
ah = ah->next;
}
// Content-Type (if available)
if (mime_type_size > 0 && mime_type) {
headers_vec[0].iov_base = "Content-Type: ";
headers_vec[0].iov_len = 14;
headers_vec[1].iov_base = mime_type;
headers_vec[1].iov_len = mime_type_size;
headers_vec[2].iov_base = "\r\n";
headers_vec[2].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
wsgi_req->header_cnt++;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "Content-Type: ", 14);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, mime_type, mime_type_size);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
}
// nginx
if (uwsgi.file_serve_mode == 1) {
wsgi_req->header_cnt += 2;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Accel-Redirect: ", 18);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, document_root, document_root_len);
if (document_root[document_root_len-1] != '/') {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "/", 1);
}
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, path_info, path_info_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
headers_vec[0].iov_base = "X-Accel-Redirect: "; headers_vec[0].iov_len = 18 ;
headers_vec[1].iov_base = real_filename; headers_vec[1].iov_len = real_filename_len;
headers_vec[2].iov_base = "\r\n"; headers_vec[2].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
// this is the final header (\r\n added)
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
wsgi_req->header_cnt += 2;
}
// apache
else if (uwsgi.file_serve_mode == 2) {
headers_vec[0].iov_base = "X-Sendfile: "; headers_vec[0].iov_len = 12 ;
headers_vec[1].iov_base = real_filename; headers_vec[1].iov_len = real_filename_len;
headers_vec[2].iov_base = "\r\n"; headers_vec[2].iov_len = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 3);
// this is the final header (\r\n added)
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
wsgi_req->header_cnt += 2;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Sendfile: ", 12);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, document_root, document_root_len);
if (document_root[document_root_len-1] != '/') {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "/", 1);
}
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, path_info, path_info_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
}
// raw
else {
wsgi_req->header_cnt += 1;
// set Content-Length
headers_vec[0].iov_base = "Content-Length: ";
headers_vec[0].iov_len = 16;
headers_vec[1].iov_len = uwsgi_long2str2n(st.st_size, content_length, sizeof(UMAX64_STR)+1);
headers_vec[1].iov_base = content_length;
headers_vec[2].iov_base = "\r\n";
headers_vec[2].iov_len = 2;
// this is the final header (\r\n added)
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
headers_vec[3].iov_base = http_last_modified;
headers_vec[3].iov_len = 48;
wsgi_req->headers_size += wsgi_req->socket->proto_writev_header(wsgi_req, headers_vec, 4);
wsgi_req->header_cnt += 2;
wsgi_req->sendfile_fd = open(real_filename, O_RDONLY);
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
// here we need to close the sendfile fd (no-GC involved)
close(wsgi_req->sendfile_fd);
}
wsgi_req->status = 200;
return 0;
}
}
return -1;
}
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t *len) {
int i;
*len = 0;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
if (!uwsgi_strncmp(key, strlen(key), wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
*len = wsgi_req->hvec[i + 1].iov_len;
return wsgi_req->hvec[i + 1].iov_base;
}
}
return NULL;
}
+86 -2
View File
@@ -33,7 +33,7 @@ int uwsgi_register_rpc(char *name, uint8_t modifier1, uint8_t args, void *func)
return ret;
}
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], char *output) {
uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], uint16_t argvs[], char *output) {
struct uwsgi_rpc *urpc = NULL;
int i;
@@ -50,9 +50,93 @@ uint16_t uwsgi_rpc(char *name, uint8_t argc, char *argv[], char *output) {
if (urpc) {
if (uwsgi.p[urpc->modifier1]->rpc) {
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, output);
ret = uwsgi.p[urpc->modifier1]->rpc(urpc->func, argc, argv, argvs, output);
}
}
return ret;
}
char *uwsgi_do_rpc(char *node, char *func, uint8_t argc, char *argv[], uint16_t argvs[], uint16_t *len) {
uint8_t i;
uint16_t ulen;
struct uwsgi_header uh;
char *buffer = NULL;
*len = 0;
if (node == NULL || !strcmp(node, "")) {
// allocate the whole buffer
buffer = uwsgi_malloc(65536);
*len = uwsgi_rpc(func, argc, argv, argvs, buffer);
return buffer;
}
// connect to node
int fd = uwsgi_connect(node, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], 0);
if (fd < 0) return NULL;
// prepare a uwsgi array
uint16_t buffer_size = 2 + strlen(func);
for (i = 0; i < argc; i++) {
buffer_size += 2 + argvs[i];
}
// allocate the whole buffer
buffer = uwsgi_malloc(65536);
uh.modifier1 = 173;
uh.pktsize = buffer_size;
uh.modifier2 = 0;
// add func to the array
char *bufptr = buffer;
ulen = strlen(func);
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, func, ulen);
bufptr += ulen;
for (i = 0; i < argc; i++) {
ulen = argvs[i];
*bufptr++ = (uint8_t) (ulen & 0xff);
*bufptr++ = (uint8_t) ((ulen >> 8) & 0xff);
memcpy(bufptr, argv[i], ulen);
bufptr += ulen;
}
if (write(fd, &uh, 4) != 4) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
if (write(fd, buffer, buffer_size) != buffer_size) {
uwsgi_error("write()");
close(fd);
free(buffer);
return NULL;
}
if (uwsgi_read_response(fd, &uh, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], &buffer) < 0) {
close(fd);
free(buffer);
return NULL;
}
close(fd);
*len = uh.pktsize;
if (*len == 0) {
free(buffer);
return NULL;
}
return buffer;
}
+11 -1
View File
@@ -106,6 +106,7 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
#else
static size_t nosf_buf_size = 0;
static char *nosf_buf;
char *nosf_buf2;
ssize_t jlen = 0;
ssize_t rlen = 0;
@@ -115,7 +116,16 @@ ssize_t uwsgi_do_sendfile(int sockfd, int filefd, size_t filesize, size_t chunk,
nosf_buf = malloc(chunk);
}
else if (chunk != nosf_buf_size) {
nosf_buf = realloc(nosf_buf, chunk);
nosf_buf2 = realloc(nosf_buf, chunk);
if (!nosf_buf2) {
free(nosf_buf);
}
nosf_buf = nosf_buf2;
}
if (!nosf_buf) {
uwsgi_error("sendfile malloc()/realloc()");
return 0;
}
nosf_buf_size = chunk;
+15 -9
View File
@@ -10,13 +10,15 @@ from setuptools.command.install_lib import install_lib
from setuptools.command.build_ext import build_ext
"""
This is a hack allowing you installing uWSGI and uwsgidecorators via pip and easy_install
This is a hack allowing you installing
uWSGI and uwsgidecorators via pip and easy_install
"""
uwsgi_compiled = False
def get_profile():
profile = os.environ.get('UWSGI_PROFILE','buildconf/default.ini')
profile = os.environ.get('UWSGI_PROFILE', 'buildconf/default.ini')
if not profile.endswith('.ini'):
profile = "%s.ini" % profile
if not '/' in profile:
@@ -24,6 +26,7 @@ def get_profile():
return profile
def patch_bin_path(cmd, conf):
bin_name = conf.get('bin_name')
@@ -33,7 +36,8 @@ def patch_bin_path(cmd, conf):
os.makedirs(cmd.install_scripts)
if not os.path.isabs(bin_name):
print('Patching "bin_name" to properly install_scripts dir')
conf.set('bin_name', os.path.join(cmd.install_scripts, conf.get('bin_name')))
conf.set('bin_name',
os.path.join(cmd.install_scripts, conf.get('bin_name')))
except:
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
@@ -45,7 +49,7 @@ class uWSGIBuilder(build_ext):
if not uwsgi_compiled:
conf = uc.uConf(get_profile())
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
uc.build_uwsgi(conf)
uwsgi_compiled = True
@@ -56,10 +60,11 @@ class uWSGIInstall(install):
if not uwsgi_compiled:
conf = uc.uConf(get_profile())
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
uc.build_uwsgi(conf)
uwsgi_compiled = True
install.run(self)
class uWSGIInstallLib(install_lib):
def run(self):
@@ -67,10 +72,11 @@ class uWSGIInstallLib(install_lib):
if not uwsgi_compiled:
conf = uc.uConf(get_profile())
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
uc.build_uwsgi(conf)
uwsgi_compiled = True
install_lib.run(self)
class uWSGIDistribution(Distribution):
def __init__(self, *attrs):
@@ -79,6 +85,7 @@ class uWSGIDistribution(Distribution):
self.cmdclass['install_lib'] = uWSGIInstallLib
self.cmdclass['build_ext'] = uWSGIBuilder
setup(name='uWSGI',
version=uc.uwsgi_version,
description='The uWSGI server',
@@ -86,7 +93,6 @@ setup(name='uWSGI',
author_email='info@unbit.it',
url='http://projects.unbit.it/uwsgi/',
license='GPL2',
py_modules = ['uwsgidecorators'],
distclass = uWSGIDistribution,
py_modules=['uwsgidecorators'],
distclass=uWSGIDistribution,
)
+31 -2
View File
@@ -12,6 +12,28 @@ int uwsgi_signal_handler(uint8_t sig) {
return -1;
}
// check for COW
if (uwsgi.master_process) {
if (use->wid != 0 && use->wid != uwsgi.mywid) {
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
return -1;
}
}
// in lazy mode (without a master), only the same worker will be able to run handlers
else if (uwsgi.lazy) {
if (use->wid != uwsgi.mywid) {
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
return -1;
}
}
else {
// when master is not active, worker1 is the COW-leader
if (use->wid != 1 && use->wid != uwsgi.mywid) {
uwsgi_log("[uwsgi-signal] you have registered this signal in worker %d memory area, only that process will be able to run it\n", use->wid);
return -1;
}
}
// set harakiri here (if required and if i am a worker)
if (uwsgi.mywid > 0) {
@@ -81,15 +103,22 @@ int uwsgi_register_signal(uint8_t sig, char *receiver, void *handler, uint8_t mo
use = &uwsgi.shared->signal_table[sig];
if (use->handler) {
uwsgi_log("[uwsgi-signal] you cannot re-register a signal !!!\n");
uwsgi_unlock(uwsgi.signal_table_lock);
return -1;
}
strcpy(use->receiver, receiver);
use->handler = handler;
use->modifier1 = modifier1;
use->wid = uwsgi.mywid;
if (use->receiver[0] == 0) {
uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: default, any worker)\n", sig, modifier1);
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: default, any worker)\n", sig, uwsgi.mywid, modifier1);
}
else {
uwsgi_log("[uwsgi-signal] signum %d registered (modifier1: %d target: %s)\n", sig, modifier1, receiver);
uwsgi_log("[uwsgi-signal] signum %d registered (wid: %d modifier1: %d target: %s)\n", sig, uwsgi.mywid, modifier1, receiver);
}
uwsgi_unlock(uwsgi.signal_table_lock);
+47 -3
View File
@@ -2,6 +2,43 @@
extern struct uwsgi_server uwsgi;
char *uwsgi_getsockname(int fd) {
socklen_t socket_type_len = sizeof(struct sockaddr_un);
union uwsgi_sockaddr usa;
union uwsgi_sockaddr_ptr gsa;
char computed_port[6];
char ipv4a[INET_ADDRSTRLEN + 1];
gsa.sa = (struct sockaddr *) &usa;
if (!getsockname(fd, gsa.sa, &socket_type_len)) {
if (gsa.sa->sa_family == AF_UNIX) {
if (usa.sa_un.sun_path[0] == 0) {
return uwsgi_concat2("@", usa.sa_un.sun_path+1);
}
else {
return uwsgi_str(usa.sa_un.sun_path);
}
}
else {
memset(ipv4a, 0, INET_ADDRSTRLEN + 1);
memset(computed_port, 0, 6);
if (snprintf(computed_port, 6, "%d", ntohs(gsa.sa_in->sin_port)) > 0) {
if (inet_ntop(AF_INET, (const void *) &gsa.sa_in->sin_addr.s_addr, ipv4a, INET_ADDRSTRLEN)) {
if (!strcmp("0.0.0.0", ipv4a)) {
return uwsgi_concat2(":", computed_port);
}
else {
return uwsgi_concat3(ipv4a, ":", computed_port);
}
}
}
}
}
return NULL;
}
int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abstract_socket) {
int serverfd;
@@ -460,15 +497,18 @@ socklen_t socket_to_un_addr(char *socket_name, struct sockaddr_un *sun_addr) {
return sizeof(sun_addr->sun_family)+len;
}
socklen_t socket_to_in_addr(char *socket_name, char *port, struct sockaddr_in *sin_addr) {
socklen_t socket_to_in_addr(char *socket_name, char *port, int portn, struct sockaddr_in *sin_addr) {
memset(sin_addr, 0, sizeof(struct sockaddr_in));
sin_addr->sin_family = AF_INET;
if (port) {
port[0] = 0;
*port = 0;
sin_addr->sin_port = htons(atoi(port + 1));
}
else {
sin_addr->sin_port = htons(portn);
}
if (socket_name[0] == 0) {
sin_addr->sin_addr.s_addr = INADDR_ANY;
@@ -483,6 +523,10 @@ socklen_t socket_to_in_addr(char *socket_name, char *port, struct sockaddr_in *s
}
}
if (port) {
*port = ':';
}
return sizeof(struct sockaddr_in);
}
@@ -493,7 +537,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
struct sockaddr_in uws_addr;
int reuse = 1;
socket_to_in_addr(socket_name, tcp_port, &uws_addr);
socket_to_in_addr(socket_name, tcp_port, 0, &uws_addr);
serverfd = socket(AF_INET, SOCK_STREAM, 0);
if (serverfd < 0) {
+5 -5
View File
@@ -65,13 +65,13 @@ void destroy_spool(char *dir, char *file) {
if (chdir(dir)) {
uwsgi_error("chdir()");
uwsgi_log("something horrible happened to the spooler. Better to kill it.\n");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
if (unlink(file)) {
uwsgi_error("unlink()");
uwsgi_log("something horrible happened to the spooler. Better to kill it.\n");
uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
exit(1);
}
@@ -165,7 +165,7 @@ int spool_request(char *filename, int rn, int core_id, char *buffer, int size, c
close(fd);
uwsgi_log("written %d bytes to spool file %s\n", size + body_len + 4, filename);
uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);
uwsgi_unlock(uwsgi.spooler_lock);
@@ -347,7 +347,7 @@ void spooler_manage_task(char *dir, char *task) {
return;
}
if (!access(task, R_OK | W_OK)) {
uwsgi_log("managing spool request %s ...\n", task);
uwsgi_log("[spooler] managing request %s ...\n", task);
#ifdef __sun__
// lockf needs write permission
@@ -426,7 +426,7 @@ void spooler_manage_task(char *dir, char *task) {
if (ret == 0) continue;
callable_found = 1;
if (ret == -2) {
uwsgi_log("done with task/spool %s after %d seconds\n", task, time(NULL)-now);
uwsgi_log("[spooler] done with task %s after %d seconds\n", task, time(NULL)-now);
destroy_spool(dir, task);
}
// re-spool it
+105 -24
View File
@@ -61,6 +61,8 @@ struct uwsgi_subscribe_slot *uwsgi_get_subscribe_slot(struct uwsgi_subscribe_slo
}
#endif
current_slot = current_slot->next;
// check for loopy optimization
if (current_slot == *slot) break;
}
return NULL;
@@ -83,6 +85,7 @@ struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slo
if (current - node->last_check > uwsgi.subscription_tolerance) {
if (node->death_mark == 0)
uwsgi_log("[uwsgi-subscription] %.*s => marking %.*s as failed (no announce received in %d seconds)\n", (int) keylen, key, (int) node->len, node->name, uwsgi.subscription_tolerance);
node->failcnt++;
node->death_mark = 1;
}
if (node->death_mark && node->reference == 0) {
@@ -95,7 +98,8 @@ struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slo
}
continue;
}
if (rr_pos == current_slot->rr) {
// only unmarked nodes can respond
if (node->death_mark == 0 && rr_pos == current_slot->rr) {
current_slot->rr++;
node->reference++;
return node;
@@ -103,8 +107,10 @@ struct uwsgi_subscribe_node *uwsgi_get_subscribe_node(struct uwsgi_subscribe_slo
node = node->next;
rr_pos++;
}
current_slot->rr = 0;
current_slot->rr = 1;
if (current_slot->nodes) {
if (current_slot->nodes->death_mark)
return NULL;
current_slot->nodes->reference++;
}
return current_slot->nodes;
@@ -159,6 +165,20 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
free(node);
// no more nodes, remove the slot too
if (node_slot->nodes == NULL) {
ret = 1;
// first check if i am the only node
if ((!prev_slot && !next_slot) || next_slot == node_slot) {
free(node_slot);
*slot = NULL;
goto end;
}
// if i am the main entry point, set the next value
if (node_slot == *slot) {
*slot = next_slot;
}
if (prev_slot) {
prev_slot->next = next_slot;
@@ -176,14 +196,16 @@ int uwsgi_remove_subscribe_node(struct uwsgi_subscribe_slot **slot, struct uwsgi
}
#endif
ret = 1;
free(node_slot);
// am i the only slot ?
if (!prev_slot && !next_slot) {
*slot = NULL;
struct uwsgi_subscribe_slot *x_slot = *slot;
while(x_slot) {
x_slot = x_slot->next;
}
}
end:
return ret;
}
@@ -198,9 +220,11 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node = current_slot->nodes;
while(node) {
if (!uwsgi_strncmp(node->name, node->len, usr->address, usr->address_len)) {
// remove death mark
// remove death mark and update cores and load
node->death_mark = 0;
node->last_check = time(NULL);
node->cores = usr->cores;
node->load = usr->load;
return node;
}
old_node = node;
@@ -211,8 +235,13 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
node->len = usr->address_len;
node->modifier1 = usr->modifier1;
node->modifier2 = usr->modifier2;
node->requests = 0;
node->transferred = 0;
node->reference = 0;
node->death_mark = 0;
node->failcnt = 0;
node->cores = usr->cores;
node->load = usr->load;
node->last_check = time(NULL);
node->slot = current_slot;
memcpy(node->name, usr->address, usr->address_len);
@@ -247,9 +276,14 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
current_slot->nodes->slot = current_slot;
current_slot->nodes->len = usr->address_len;
current_slot->nodes->reference = 0;
current_slot->nodes->requests = 0;
current_slot->nodes->transferred = 0;
current_slot->nodes->death_mark = 0;
current_slot->nodes->failcnt = 0;
current_slot->nodes->modifier1 = usr->modifier1;
current_slot->nodes->modifier2 = usr->modifier2;
current_slot->nodes->cores = usr->cores;
current_slot->nodes->load = usr->load;
memcpy(current_slot->nodes->name, usr->address, usr->address_len);
current_slot->nodes->last_check = time(NULL);
@@ -325,13 +359,21 @@ struct uwsgi_subscribe_node *uwsgi_add_subscribe_node(struct uwsgi_subscribe_slo
}
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, char *modifier1, size_t modifier1_len, uint8_t cmd) {
void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, uint8_t modifier1, uint8_t modifier2, uint8_t cmd) {
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(uwsgi.sockets->name));
char value_cores[sizeof(UMAX64_STR)+1];
char value_load[sizeof(UMAX64_STR)+1];
char value_modifier1[4];
char value_modifier2[4];
int value_cores_size = uwsgi_long2str2n(uwsgi.numproc*uwsgi.cores, value_cores, sizeof(UMAX64_STR));
int value_load_size = uwsgi_long2str2n(uwsgi.shared->load, value_load, sizeof(UMAX64_STR));
int value_modifier1_size = uwsgi_long2str2n(modifier1, value_modifier1, 3);
int value_modifier2_size = uwsgi_long2str2n(modifier2, value_modifier2, 3);
if (modifier1) {
ssb_size += (2 + 9) + (2 + modifier1_len);
}
if (!uwsgi.sockets) return;
size_t ssb_size = 4 + (2 + 3) + (2 + keysize) + (2 + 7) + (2 + strlen(uwsgi.sockets->name)) + (2+9 + 2+value_modifier1_size) +
(2+9 + 2+value_modifier2_size) + (2+5 + 2+value_cores_size) + (2+4 + 2+value_load_size);
char *subscrbuf = uwsgi_malloc(ssb_size);
// leave space for uwsgi header
@@ -364,20 +406,59 @@ void uwsgi_send_subscription(char *udp_address, char *key, size_t keysize, char
ssb+=ustrlen;
// modifier1 = "modifier1"
if (modifier1) {
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "modifier1", ustrlen);
ssb+=ustrlen;
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "modifier1", ustrlen);
ssb+=ustrlen;
ustrlen = modifier1_len;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, modifier1, ustrlen);
ssb+=ustrlen;
}
ustrlen = value_modifier1_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_modifier1, value_modifier1_size);
ssb+=ustrlen;
// modifier2 = "modifier2"
ustrlen = 9;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "modifier2", ustrlen);
ssb+=ustrlen;
ustrlen = value_modifier2_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_modifier2, value_modifier2_size);
ssb+=ustrlen;
// cores = uwsgi.numproc * uwsgi.cores
ustrlen = 5;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "cores", ustrlen);
ssb+=ustrlen;
ustrlen = value_cores_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_cores, value_cores_size);
ssb+=ustrlen;
// load
ustrlen = 4;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, "load", ustrlen);
ssb+=ustrlen;
ustrlen = value_load_size;
*ssb++ = (uint8_t) (ustrlen & 0xff);
*ssb++ = (uint8_t) ((ustrlen >>8) & 0xff);
memcpy(ssb, value_load, value_load_size);
ssb+=ustrlen;
send_udp_message(224, cmd, udp_address, subscrbuf, ssb_size-4);
free(subscrbuf);
}
+247 -122
View File
@@ -275,52 +275,53 @@ void logto(char *logfile) {
}
#ifdef UWSGI_ZEROMQ
void log_zeromq(char *node) {
ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *ul, char *message, size_t len) {
void *ctx = zmq_init(1);
if (ctx == NULL) {
uwsgi_error("zmq_init()");
exit(1);
if (!ul->configured) {
if (!uwsgi.choosen_logger_arg) {
uwsgi_log_safe("invalid zeromq syntax\n");
exit(1);
}
void *ctx = zmq_init(1);
if (ctx == NULL) {
uwsgi_error_safe("zmq_init()");
exit(1);
}
ul->data = zmq_socket(ctx, ZMQ_PUSH);
if (ul->data == NULL) {
uwsgi_error_safe("zmq_socket()");
exit(1);
}
if (zmq_connect(ul->data, uwsgi.choosen_logger_arg) < 0) {
uwsgi_error_safe("zmq_connect()");
exit(1);
}
ul->configured = 1;
}
zmq_msg_t msg;
if (zmq_msg_init_size (&msg, len) == 0) {
memcpy(zmq_msg_data(&msg), message, len);
zmq_send(ul->data, &msg, 0);
zmq_msg_close(&msg);
}
uwsgi.zmq_log_socket = zmq_socket(ctx, ZMQ_PUSH);
if (uwsgi.zmq_log_socket == NULL) {
uwsgi_error("zmq_socket()");
exit(1);
}
if (zmq_connect(uwsgi.zmq_log_socket, node) < 0) {
uwsgi_error("zmq_connect()");
exit(1);
}
return 0;
}
#endif
void log_socket(char *socket_name) {
int family = AF_UNIX;
uwsgi.log_socket_addr = uwsgi_malloc(sizeof(union uwsgi_sockaddr));
char *colon = strchr(socket_name, ':');
if (colon) {
family = AF_INET;
uwsgi.log_socket_size = socket_to_in_addr(socket_name, colon, &uwsgi.log_socket_addr->sa_in);
}
else {
uwsgi.log_socket_size = socket_to_un_addr(socket_name, &uwsgi.log_socket_addr->sa_un);
}
uwsgi.log_socket_fd = socket(family, SOCK_DGRAM, 0);
if (uwsgi.log_socket_fd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
}
}
void create_logpipe(void) {
#if defined(SOCK_SEQPACKET) && defined(__linux__)
if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
#else
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
#endif
uwsgi_error("socketpair()\n");
exit(1);
}
@@ -342,22 +343,6 @@ void create_logpipe(void) {
}
void log_syslog(char *syslog_opts) {
setlinebuf(stderr);
if (syslog_opts == NULL) {
syslog_opts = "uwsgi";
}
#ifdef UWSGI_DEBUG
uwsgi_log("opening syslog\n");
#endif
openlog(syslog_opts, 0, LOG_DAEMON);
}
char *uwsgi_get_cwd() {
// set this to static to avoid useless reallocations in stats mode
@@ -514,6 +499,20 @@ void uwsgi_as_root() {
}
#endif
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
if (uwsgi.unshare && !uwsgi.reloads) {
if (unshare(uwsgi.unshare)) {
uwsgi_error("unshare()");
exit(1);
}
else {
uwsgi_log("[linux-namespace] applied unshare() mask: %d\n", uwsgi.unshare);
}
}
#endif
if (uwsgi.chroot && !uwsgi.reloads) {
if (!uwsgi.master_as_root)
uwsgi_log("chroot() to %s\n", uwsgi.chroot);
@@ -528,6 +527,18 @@ void uwsgi_as_root() {
#endif
}
// now run the scripts needed by root
struct uwsgi_string_list *usl = uwsgi.exec_as_root;
while(usl) {
uwsgi_log("running \"%s\" (as root)...\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;
}
if (uwsgi.gidname) {
struct group *ugroup = getgrnam(uwsgi.gidname);
if (ugroup) {
@@ -603,6 +614,18 @@ void uwsgi_as_root() {
cap_free(caps);
}
#endif
// now run the scripts needed by the user
usl = uwsgi.exec_as_user;
while(usl) {
uwsgi_log("running \"%s\" (as uid: %d gid: %d) ...\n", usl->value, (int) getuid(), (int) getgid());
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;
}
}
else {
if (uwsgi.chroot && !uwsgi.is_a_reload) {
@@ -739,81 +762,76 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
#ifdef __linux__
#ifdef MADV_MERGEABLE
unsigned long long *ksm_mappings_last = NULL;
int ksm_mappings_last_lines = 0;
unsigned long long *ksm_mappings_current = NULL;
int ksm_mappings_current_lines = 0;
void uwsgi_linux_ksm_map(void) {
char map_line_buf[1024];
unsigned long long start, end;
int dirty = 0;
int i;
int errors = 0;
unsigned long long *tmp_ptr;
size_t i;
unsigned long long start = 0, end = 0;
int errors = 0; int lines = 0;
ksm_mappings_current = NULL;
ksm_mappings_current_lines = 0;
int fd = open("/proc/self/maps", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("[uwsgi-KSM] /proc/self/maps");
return ;
}
FILE *process_maps = fopen("/proc/self/maps", "r");
// allocate memory if not available;
if (uwsgi.ksm_mappings_current == NULL) {
if (!uwsgi.ksm_buffer_size) uwsgi.ksm_buffer_size = 32768;
uwsgi.ksm_mappings_current = uwsgi_malloc(uwsgi.ksm_buffer_size);
uwsgi.ksm_mappings_current_size = 0;
}
if (uwsgi.ksm_mappings_last == NULL) {
if (!uwsgi.ksm_buffer_size) uwsgi.ksm_buffer_size = 32768;
uwsgi.ksm_mappings_last = uwsgi_malloc(uwsgi.ksm_buffer_size);
uwsgi.ksm_mappings_last_size = 0;
}
if (process_maps) {
while( fgets(map_line_buf, 1024, process_maps)) {
if (fscanf(process_maps, "%llx-%llx %*s", &start, &end) == 2) {
ksm_mappings_current_lines+=2;
tmp_ptr = ksm_mappings_current;
ksm_mappings_current = realloc(ksm_mappings_current, sizeof(unsigned long long) * ksm_mappings_current_lines);
if (!ksm_mappings_current) {
uwsgi_error("[uwsgi-KSM] /proc/self/maps realloc()");
fclose(process_maps);
if (tmp_ptr) {
free(tmp_ptr);
}
return;
}
ksm_mappings_current[ksm_mappings_current_lines-2] = start;
ksm_mappings_current[ksm_mappings_current_lines-1] = end;
}
}
fclose(process_maps);
uwsgi.ksm_mappings_current_size = read(fd, uwsgi.ksm_mappings_current, uwsgi.ksm_buffer_size);
close(fd);
if (uwsgi.ksm_mappings_current_size <= 0) {
uwsgi_log("[uwsgi-KSM] unable to read /proc/self/maps data\n");
return;
}
if (ksm_mappings_last == NULL || ksm_mappings_last_lines == 0 || ksm_mappings_last_lines != ksm_mappings_current_lines) {
// we now have areas
if (uwsgi.ksm_mappings_last_size == 0 || uwsgi.ksm_mappings_current_size == 0 || uwsgi.ksm_mappings_current_size != uwsgi.ksm_mappings_last_size) {
dirty = 1;
}
else {
if (memcmp(uwsgi.ksm_mappings_current, uwsgi.ksm_mappings_last, uwsgi.ksm_mappings_current_size) != 0) {
dirty = 1;
}
else {
for(i=0;i<ksm_mappings_current_lines;i+=2) {
if (ksm_mappings_current[i] != ksm_mappings_last[i]) {
dirty = 1;
break;
}
if (ksm_mappings_current[i+1] != ksm_mappings_last[i+1]) {
dirty = 1;
break;
}
// it is dirty, swap addresses and parse it
if (dirty) {
char *tmp = uwsgi.ksm_mappings_last;
uwsgi.ksm_mappings_last = uwsgi.ksm_mappings_current;
uwsgi.ksm_mappings_current = tmp;
size_t tmp_size = uwsgi.ksm_mappings_last_size;
uwsgi.ksm_mappings_last_size = uwsgi.ksm_mappings_current_size;
uwsgi.ksm_mappings_current_size = tmp_size;
// scan each line and call madvise on it
char *ptr = uwsgi.ksm_mappings_last;
for(i=0;i<uwsgi.ksm_mappings_last_size;i++) {
if (uwsgi.ksm_mappings_last[i] == '\n') {
lines++;
uwsgi.ksm_mappings_last[i] = 0;
if (sscanf(ptr, "%llx-%llx %*s", &start, &end) == 2) {
if (madvise((void *) (long) start, (size_t) (end-start), MADV_MERGEABLE)) {
errors ++;
}
}
uwsgi.ksm_mappings_last[i] = '\n';
ptr = uwsgi.ksm_mappings_last+i+1;
}
}
if (dirty) {
for(i=0;i<ksm_mappings_current_lines;i+=2) {
if (madvise((void *) (long) ksm_mappings_current[i], (size_t) (ksm_mappings_current[i+1]-ksm_mappings_current[i]), MADV_MERGEABLE)) {
errors += 2;
}
}
if (ksm_mappings_last)
free(ksm_mappings_last);
ksm_mappings_last = ksm_mappings_current;
ksm_mappings_last_lines = ksm_mappings_current_lines;
if (errors >= ksm_mappings_current_lines) {
uwsgi_error("[uwsgi-KSM] unable to share pages");
}
}
// if not dirty, free ksm_mappings_current
else {
free(ksm_mappings_current);
if (errors >= lines) {
uwsgi_error("[uwsgi-KSM] unable to share pages");
}
}
}
@@ -1081,7 +1099,7 @@ void parse_sys_envs(char **envs) {
char *earg, *eq_pos;
while (*uenvs) {
if (!strncmp(*uenvs, "UWSGI_", 6) && strncmp(*uenvs, "UWSGI_RELOADS=", 14)) {
if (!strncmp(*uenvs, "UWSGI_", 6) && strncmp(*uenvs, "UWSGI_RELOADS=", 14) && strncmp(*uenvs, "UWSGI_ORIGINAL_PROC_NAME=", 25)) {
earg = uwsgi_malloc(strlen(*uenvs + 6) + 1);
env_to_arg(*uenvs + 6, earg);
eq_pos = strchr(earg, '=');
@@ -1653,11 +1671,18 @@ int uwsgi_read_whole_body(struct wsgi_request *wsgi_req, char *buf, size_t len)
else {
post_chunk = read(wsgi_req->poll.fd, buf, post_remains);
}
if (post_chunk < 0) {
uwsgi_error("read()");
goto end;
}
if (!fwrite(buf, post_chunk, 1, wsgi_req->async_post)) {
if (post_chunk == 0) {
uwsgi_log("client did not send the whole body: %s\n", strerror(errno));
goto end;
}
if (fwrite(buf, post_chunk, 1, wsgi_req->async_post) != 1) {
uwsgi_error("fwrite()");
goto end;
}
@@ -2145,6 +2170,7 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
if (S_ISFIFO(sb.st_mode)) {
buffer = uwsgi_read_fd(fd, size, add_zero);
close(fd);
goto end;
}
@@ -2355,6 +2381,12 @@ int uwsgi_num2str2n(int num, char *ptr, int size) {
return snprintf(ptr, size, "%d", num);
}
int uwsgi_long2str2n(unsigned long long num, char *ptr, int size) {
int ret = snprintf(ptr, size, "%llu", num);
if (ret < 0) return 0;
return ret;
}
int is_unix(char *socket_name, int len) {
int i;
for (i = 0; i < len; i++) {
@@ -2804,7 +2836,7 @@ void uwsgi_sig_pause() {
int uwsgi_run_command_and_wait(char *command, char *arg) {
char *argv[3];
char *argv[4];
int waitpid_status = 0;
pid_t pid = fork();
if (pid < 0) {
@@ -2820,11 +2852,26 @@ int uwsgi_run_command_and_wait(char *command, char *arg) {
return WEXITSTATUS(waitpid_status);
}
argv[0] = command;
argv[1] = arg;
argv[2] = NULL;
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
if (command == NULL) {
argv[0] = "/bin/sh";
argv[1] = "-c";
argv[2] = arg;
argv[3] = NULL;
execvp(argv[0], argv);
}
else {
argv[0] = command;
argv[1] = arg;
argv[2] = NULL;
execvp(command, argv);
}
execvp(command, argv);
uwsgi_error("execvp()");
//never here
@@ -3148,6 +3195,70 @@ void uwsgi_build_mime_dict(char *filename) {
}
#ifdef __linux__
struct uwsgi_unshare_id {
char *name;
int value;
};
static struct uwsgi_unshare_id uwsgi_unshare_list[] = {
#ifdef CLONE_FILES
{"files", CLONE_FILES},
#endif
#ifdef CLONE_FS
{"fs", CLONE_FS},
#endif
#ifdef CLONE_NEWIPC
{"ipc", CLONE_NEWIPC},
#endif
#ifdef CLONE_NEWNET
{"net", CLONE_NEWNET},
#endif
#ifdef CLONE_NEWPID
{"pid", CLONE_NEWPID},
#endif
#ifdef CLONE_NEWNS
{"ns", CLONE_NEWNS},
{"mount", CLONE_NEWNS},
#endif
#ifdef CLONE_SYSVSEM
{"sysvsem", CLONE_SYSVSEM},
#endif
#ifdef CLONE_NEWUTS
{"uts", CLONE_NEWUTS},
#endif
{ NULL, -1}
};
static int uwsgi_get_unshare_id(char *name) {
struct uwsgi_unshare_id *uui = uwsgi_unshare_list;
while(uui->name) {
if (!strcmp(uui->name, name)) return uui->value;
uui++;
}
return -1;
}
void uwsgi_build_unshare(char *what) {
char *list = uwsgi_str(what);
char *p = strtok(list, ",");
while (p != NULL) {
int u_id = uwsgi_get_unshare_id(p);
if (u_id != -1) {
uwsgi.unshare |= u_id;
}
p = strtok(NULL, ",");
}
free(list);
}
#endif
#ifdef UWSGI_CAP
struct uwsgi_cap {
char *name;
@@ -3442,6 +3553,20 @@ void http_url_decode(char *buf, uint16_t *len, char *dst) {
}
char *uwsgi_get_var(struct wsgi_request *wsgi_req, char *key, uint16_t keylen, uint16_t *len) {
int i;
for (i = 0; i < wsgi_req->var_cnt; i += 2) {
if (!uwsgi_strncmp(key, keylen, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len)) {
*len = wsgi_req->hvec[i + 1].iov_len;
return wsgi_req->hvec[i + 1].iov_base;
}
}
return NULL;
}
void uwsgi_add_app(int id, uint8_t modifier1, char *mountpoint, int mountpoint_len) {
struct uwsgi_app *wi = &uwsgi_apps[id];
+233 -102
View File
@@ -1,5 +1,5 @@
/*
_socket_nb(uwsgi.shared->worker_log_pipe[1]
*** uWSGI ***
Copyright (C) 2009-2011 Unbit S.a.s. <info@unbit.it>
@@ -147,6 +147,11 @@ static struct option long_base_options[] = {
#ifdef UWSGI_CAP
{"cap", required_argument,0, LONG_ARGS_CAP},
#endif
#ifdef __linux__
{"unshare", required_argument,0, LONG_ARGS_UNSHARE},
#endif
{"exec-as-root", required_argument,0, LONG_ARGS_EXEC_AS_ROOT},
{"exec-as-user", required_argument,0, LONG_ARGS_EXEC_AS_USER},
#ifdef UWSGI_INI
{"ini", required_argument, 0, LONG_ARGS_INI},
#endif
@@ -226,6 +231,8 @@ static struct option long_base_options[] = {
{"logfile-chmod", required_argument, 0, LONG_ARGS_LOGFILE_CHMOD},
{"log-syslog", optional_argument, 0, LONG_ARGS_LOG_SYSLOG},
{"log-socket", required_argument, 0, LONG_ARGS_LOG_SOCKET},
{"logger", required_argument, 0, LONG_ARGS_LOGGER},
{"threaded-logger", no_argument, &uwsgi.threaded_logger, 1},
#ifdef UWSGI_ZEROMQ
{"log-zeromq", required_argument, 0, LONG_ARGS_LOG_ZEROMQ},
#endif
@@ -251,6 +258,7 @@ static struct option long_base_options[] = {
{"lazy", no_argument, &uwsgi.lazy, 1},
{"cheap", no_argument, &uwsgi.cheap, 1},
{"cheaper", required_argument, 0, LONG_ARGS_CHEAPER},
{"cheaper-step", required_argument, 0, LONG_ARGS_CHEAPER_STEP},
{"idle", required_argument, 0, LONG_ARGS_IDLE},
{"die-on-idle", no_argument, &uwsgi.die_on_idle, 1},
{"mount", required_argument, 0, LONG_ARGS_MOUNT},
@@ -261,6 +269,8 @@ static struct option long_base_options[] = {
{"threads", required_argument, 0, LONG_ARGS_THREADS},
{"threads-stacksize", required_argument, 0, LONG_ARGS_THREADS_STACKSIZE},
{"thread-stacksize", required_argument, 0, LONG_ARGS_THREADS_STACKSIZE},
{"threads-stack-size", required_argument, 0, LONG_ARGS_THREADS_STACKSIZE},
{"thread-stack-size", required_argument, 0, LONG_ARGS_THREADS_STACKSIZE},
{"vhost", no_argument, &uwsgi.vhost, 1},
{"vhost-host", no_argument, 0, LONG_ARGS_VHOSTHOST},
#ifdef UWSGI_ROUTING
@@ -268,10 +278,14 @@ static struct option long_base_options[] = {
#endif
{"add-header", required_argument, 0, LONG_ARGS_ADD_HEADER},
{"check-static", required_argument, 0, LONG_ARGS_CHECK_STATIC},
{"static-check", required_argument, 0, LONG_ARGS_CHECK_STATIC},
{"static-skip-ext", required_argument, 0, LONG_ARGS_STATIC_SKIP_EXT},
{"static-map", required_argument, 0, LONG_ARGS_STATIC_MAP},
{"static-index", required_argument, 0, LONG_ARGS_STATIC_INDEX},
{"mimefile", required_argument, 0, LONG_ARGS_MIMEFILE},
{"mime-file", required_argument, 0, LONG_ARGS_MIMEFILE},
{"file-serve-mode", required_argument, 0, LONG_ARGS_FILE_SERVE_MODE},
{"fileserve-mode", required_argument, 0, LONG_ARGS_FILE_SERVE_MODE},
{"check-cache", no_argument, &uwsgi.check_cache, 1},
{"close-on-exec", no_argument, &uwsgi.close_on_exec, 1},
{"mode", required_argument, 0, LONG_ARGS_MODE},
@@ -303,6 +317,74 @@ static struct option long_base_options[] = {
{0, 0, 0, 0}
};
void show_config(void) {
int i;
fprintf(stdout, "\n;uWSGI instance configuration\n[uwsgi]\n");
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->value) {
fprintf(stdout, "%s = %s\n", uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
}
else {
fprintf(stdout, "%s = true\n", uwsgi.exported_opts[i]->key);
}
}
fprintf(stdout, ";end of configuration\n\n");
}
void uwsgi_apply_templates(void) {
struct uwsgi_config_template *uct = uwsgi.config_templates;
while (uct) {
if (uct->applied) {
uct = uct->next;
continue;
}
uwsgi_log("using %s as config template\n", uct->filename);
#ifdef UWSGI_XML
if (!strcmp(uct->filename + strlen(uct->filename) - 4, ".xml")) {
uwsgi_xml_config(uct->filename, uwsgi.wsgi_req, 0, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_INI
if (!strcmp(uct->filename + strlen(uct->filename) - 4, ".ini")) {
uwsgi_ini_config(uct->filename, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_YAML
if (!strcmp(uct->filename + strlen(uct->filename) - 4, ".yml")) {
uwsgi_yaml_config(uct->filename, uwsgi.magic_table);
}
if (!strcmp(uct->filename + strlen(uct->filename) - 5, ".yaml")) {
uwsgi_yaml_config(uct->filename, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_JSON
if (!strcmp(uct->filename + strlen(uct->filename) - 3, ".js")) {
uwsgi_json_config(uct->filename, uwsgi.magic_table);
}
if (!strcmp(uct->filename + strlen(uct->filename) - 5, ".json")) {
uwsgi_json_config(uct->filename, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_SQLITE3
if (!strcmp(uct->filename + strlen(uct->filename) - 3, ".db")) {
uwsgi_sqlite3_config(uct->filename, uwsgi.magic_table);
}
if (!strcmp(uct->filename + strlen(uct->filename) - 7, ".sqlite")) {
uwsgi_sqlite3_config(uct->filename, uwsgi.magic_table);
}
if (!strcmp(uct->filename + strlen(uct->filename) - 8, ".sqlite3")) {
uwsgi_sqlite3_config(uct->filename, uwsgi.magic_table);
}
#endif
uct->applied = 1;
uct = uct->next;
}
}
void uwsgi_configure(void) {
struct option *lopt;
@@ -312,18 +394,32 @@ void uwsgi_configure(void) {
int is_retry;
int found;
// option must be processed in reverse (to have a consistent template system)
// but first load plugins...
// plugins and inherit must be processed first (to have a consistent template system)
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->configured)
continue;
if (!strcmp("plugin", uwsgi.exported_opts[i]->key) || !strcmp("plugins", uwsgi.exported_opts[i]->key)) {
manage_opt(LONG_ARGS_PLUGINS, uwsgi.exported_opts[i]->value);
uwsgi.exported_opts[i]->configured = 1;
}
else if (!strcmp("inherit", uwsgi.exported_opts[i]->key)) {
manage_opt(LONG_ARGS_INHERIT, uwsgi.exported_opts[i]->value);
uwsgi.exported_opts[i]->configured = 1;
}
else if (!strcmp("vassals-inherit", uwsgi.exported_opts[i]->key)) {
manage_opt(LONG_ARGS_VASSALS_INHERIT, uwsgi.exported_opts[i]->value);
uwsgi.exported_opts[i]->configured = 1;
}
}
for (i = uwsgi.exported_opts_cnt-1; i >= 0; i--) {
// apply templates (again)
uwsgi_apply_templates();
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
#ifdef UWSGI_DEBUG
uwsgi_log("i = %d %p\n", i, uwsgi.exported_opts[i]);
@@ -348,7 +444,7 @@ void uwsgi_configure(void) {
*aopt->flag = aopt->val;
else if (val) {
if (aopt->has_arg == optional_argument) {
if (!strcasecmp("true", val)) {
if (!strcasecmp("true", val) || !strcmp("1", val)) {
val = NULL;
}
}
@@ -765,6 +861,7 @@ void stats(int signum) {
int i, j;
if (uwsgi.mywid == 0) {
show_config();
uwsgi_log("\tworkers total requests: %llu\n", uwsgi.workers[0].requests);
uwsgi_log("-----------------\n");
for(j=1;j<=uwsgi.numproc;j++) {
@@ -992,6 +1089,9 @@ void fixup_argv_and_environ(int argc, char **argv, char **environ) {
#endif
}
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int argc, char *argv[], char *envp[]) {
@@ -1184,6 +1284,16 @@ int main(int argc, char *argv[], char *envp[]) {
// ok we can now safely play with argv and environ
fixup_argv_and_environ(argc, argv, environ);
if (gethostname(uwsgi.hostname, 255)) {
uwsgi_error("gethostname()");
}
uwsgi.hostname_len = strlen(uwsgi.hostname);
#ifdef UWSGI_ZEROMQ
uwsgi_register_logger("zeromq", uwsgi_zeromq_logger);
uwsgi_register_logger("zmq", uwsgi_zeromq_logger);
#endif
//initialize embedded plugins
UWSGI_LOAD_EMBEDDED_PLUGINS
// now a bit of magic, if the executable basename contains a 'uwsgi_' string,
@@ -1191,14 +1301,22 @@ int main(int argc, char *argv[], char *envp[]) {
#ifdef UWSGI_DEBUG
uwsgi_log("executable name: %s\n", uwsgi.binary_path);
#endif
char *p = strrchr(uwsgi.binary_path, '/');
if (p == NULL) p = uwsgi.binary_path;
char *original_proc_name = getenv("UWSGI_ORIGINAL_PROC_NAME");
if (!original_proc_name) {
// here we use argv[0];
original_proc_name = argv[0];
setenv("UWSGI_ORIGINAL_PROC_NAME", original_proc_name, 1);
}
char *p = strrchr(original_proc_name, '/');
if (p == NULL) p = original_proc_name;
p = strstr(p, "uwsgi_");
if (p != NULL) {
plugins_requested = strchr(p, '_');
if (plugins_requested != NULL && *(++plugins_requested) != '\0') {
uwsgi_log("plugin = %s\n", plugins_requested);
uwsgi_load_plugin(0, plugins_requested, NULL, 0);
plugins_requested = strtok(uwsgi_str(p+6), "_");
while(plugins_requested) {
uwsgi_log("[uwsgi] implicit plugin requested %s\n", plugins_requested);
uwsgi_load_plugin(-1, plugins_requested, NULL, 0);
plugins_requested = strtok(NULL, "_");
}
}
@@ -1214,11 +1332,6 @@ int main(int argc, char *argv[], char *envp[]) {
build_options();
if (gethostname(uwsgi.hostname, 255)) {
uwsgi_error("gethostname()");
}
uwsgi.hostname_len = strlen(uwsgi.hostname);
uwsgi.magic_table['v'] = uwsgi.cwd;
uwsgi.magic_table['h'] = uwsgi.hostname;
@@ -1299,18 +1412,19 @@ int main(int argc, char *argv[], char *envp[]) {
}
else {
int magic = 0;
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->magic) {
if (uwsgi.gp[i]->magic(NULL, lazy)) {
int j;
for (j = 0; j< uwsgi.gp_cnt; j++) {
if (uwsgi.gp[j]->magic) {
if (uwsgi.gp[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
}
}
if (!magic) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->magic) {
if (uwsgi.p[i]->magic(NULL, lazy)) {
for (j = 0; j < 0xFF; j++) {
if (uwsgi.p[j]->magic) {
if (uwsgi.p[j]->magic(NULL, lazy)) {
magic = 1;
break;
}
@@ -1368,48 +1482,8 @@ int main(int argc, char *argv[], char *envp[]) {
//parse environ
parse_sys_envs(environ);
struct uwsgi_config_template *uct = uwsgi.config_templates;
while (uct) {
uwsgi_log("using %s as config template\n", uct->filename);
#ifdef UWSGI_XML
if (!strcmp(uct->filename + strlen(uct->filename) - 4, ".xml")) {
uwsgi_xml_config(uct->filename, uwsgi.wsgi_req, 0, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_INI
if (!strcmp(uct->filename + strlen(uct->filename) - 4, ".ini")) {
uwsgi_ini_config(uct->filename, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_YAML
if (!strcmp(uct->filename + strlen(uct->filename) - 4, ".yml")) {
uwsgi_yaml_config(uct->filename, uwsgi.magic_table);
}
if (!strcmp(uct->filename + strlen(uct->filename) - 5, ".yaml")) {
uwsgi_yaml_config(uct->filename, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_JSON
if (!strcmp(uct->filename + strlen(uct->filename) - 3, ".js")) {
uwsgi_json_config(uct->filename, uwsgi.magic_table);
}
if (!strcmp(uct->filename + strlen(uct->filename) - 5, ".json")) {
uwsgi_json_config(uct->filename, uwsgi.magic_table);
}
#endif
#ifdef UWSGI_SQLITE3
if (!strcmp(uct->filename + strlen(uct->filename) - 3, ".db")) {
uwsgi_sqlite3_config(uct->filename, uwsgi.magic_table);
}
if (!strcmp(uct->filename + strlen(uct->filename) - 7, ".sqlite")) {
uwsgi_sqlite3_config(uct->filename, uwsgi.magic_table);
}
if (!strcmp(uct->filename + strlen(uct->filename) - 8, ".sqlite3")) {
uwsgi_sqlite3_config(uct->filename, uwsgi.magic_table);
}
#endif
uct = uct->next;
}
// apply templates passed from command line
uwsgi_apply_templates();
// second pass: ENVs
uwsgi_apply_config_pass('$', (char *(*)(char *))getenv);
@@ -1420,18 +1494,34 @@ int main(int argc, char *argv[], char *envp[]) {
// last pass: REFERENCEs
uwsgi_apply_config_pass('%', uwsgi_get_exported_opt);
// ok, the options dictionary is available, lets manage it
uwsgi_configure();
// setup master logging
if (uwsgi.log_master) {
if (uwsgi.requested_logger) {
char *colon = strchr(uwsgi.requested_logger, ':');
if (colon) {
*colon = 0;
}
uwsgi.choosen_logger = uwsgi_get_logger(uwsgi.requested_logger);
if (!uwsgi.choosen_logger) {
uwsgi_log("unable to find logger %s\n", uwsgi.requested_logger);
exit(1);
}
if (colon) {
uwsgi.choosen_logger_arg = colon+1;
*colon = ':';
}
}
uwsgi.original_log_fd = dup(1);
create_logpipe();
}
/* uWSGI IS CONFIGURED !!! */
@@ -1446,16 +1536,7 @@ int main(int argc, char *argv[], char *envp[]) {
}
if (uwsgi.show_config) {
fprintf(stdout, "\n;uWSGI instance configuration\n[uwsgi]\n");
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->value) {
fprintf(stdout, "%s = %s\n", uwsgi.exported_opts[i]->key, uwsgi.exported_opts[i]->value);
}
else {
fprintf(stdout, "%s = true\n", uwsgi.exported_opts[i]->key);
}
}
fprintf(stdout, ";end of configuration\n\n");
show_config();
}
@@ -1737,6 +1818,7 @@ int uwsgi_start(void *v_argv) {
uwsgi_register_loop("simple", simple_loop);
#ifdef UWSGI_ASYNC
uwsgi_register_loop("async", async_loop);
@@ -1764,6 +1846,7 @@ int uwsgi_start(void *v_argv) {
}
}
}
#endif
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
uwsgi.max_fd = uwsgi.rl.rlim_cur;
@@ -2218,6 +2301,9 @@ skipzero:
uwsgi_log("!!! unable to set requested threads stacksize !!!\n");
}
}
pthread_mutex_init(&uwsgi.lock_static, NULL);
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->enable_threads)
uwsgi.p[i]->enable_threads();
@@ -2392,37 +2478,34 @@ skipzero:
uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
*/
uwsgi_log("*** Operational MODE: ");
if (!uwsgi.numproc) {
uwsgi_rawlog("no-workers");
uwsgi_log("*** Operational MODE: no-workers ***\n");
}
else if (uwsgi.threads > 1) {
if (uwsgi.numproc > 1) {
uwsgi_rawlog("preforking+threaded");
uwsgi_log("*** Operational MODE: preforking+threaded ***\n");
}
else {
uwsgi_rawlog("threaded");
uwsgi_log("*** Operational MODE: threaded ***\n");
}
}
#ifdef UWSGI_ASYNC
else if (uwsgi.async > 1) {
if (uwsgi.numproc > 1) {
uwsgi_rawlog("preforking+async");
uwsgi_log("*** Operational MODE: preforking+async ***\n");
}
else {
uwsgi_rawlog("async");
uwsgi_log("*** Operational MODE: async ***\n");
}
}
#endif
else if (uwsgi.numproc > 1) {
uwsgi_rawlog("preforking");
uwsgi_log("*** Operational MODE: preforking ***\n");
}
else {
uwsgi_rawlog("single process");
uwsgi_log("*** Operational MODE: single process ***\n");
}
uwsgi_rawlog(" ***\n");
// even the master has cores..
uwsgi.core = uwsgi_malloc(sizeof(struct uwsgi_core *) * uwsgi.cores);
for (j = 0; j < uwsgi.cores; j++) {
@@ -2430,6 +2513,19 @@ skipzero:
memset(uwsgi.core[j], 0, sizeof(struct uwsgi_core));
}
// preinit apps (create the language environment)
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->preinit_apps) {
uwsgi.p[i]->preinit_apps();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->preinit_apps) {
uwsgi.gp[i]->preinit_apps();
}
}
//init apps hook (if not lazy)
if (!uwsgi.lazy) {
uwsgi_init_all_apps();
@@ -2842,16 +2938,14 @@ skipzero:
// eventually remap plugins
if (uwsgi.remap_modifier) {
char *map = strtok(uwsgi.remap_modifier, ",");
struct uwsgi_plugin *up_tmp;
while (map != NULL) {
char *colon = strchr(map, ':');
if (colon) {
colon[0] = 0;
int rm_src = atoi(map);
int rm_dst = atoi(colon + 1);
up_tmp = uwsgi.p[rm_dst];
uwsgi.p[rm_dst]->request = uwsgi.p[rm_src]->request;
uwsgi.p[rm_src]->after_request = up_tmp->after_request;
uwsgi.p[rm_dst]->after_request = uwsgi.p[rm_src]->after_request;
}
map = strtok(NULL, ",");
}
@@ -2948,9 +3042,11 @@ void uwsgi_ignition() {
long y = 0;
simple_loop((void *) y);
}
#ifdef UWSGI_ASYNC
else {
async_loop(NULL);
}
#endif
}
@@ -3048,6 +3144,9 @@ static int manage_base_opt(int i, char *optarg) {
uwsgi.cheaper = 1;
uwsgi.cheaper_count = atoi(optarg);
return 1;
case LONG_ARGS_CHEAPER_STEP:
uwsgi.cheaper_step = atoi(optarg);
return 1;
case LONG_ARGS_CHDIR:
uwsgi.chdir = optarg;
return 1;
@@ -3136,22 +3235,30 @@ static int manage_base_opt(int i, char *optarg) {
uwsgi.log_master = 1;
return 1;
case LONG_ARGS_LOG_SOCKET:
uwsgi.log_socket = 1;
uwsgi.log_master = 1;
uwsgi.master_process = 1;
log_socket(optarg);
uwsgi.requested_logger = uwsgi_concat2("socket:", optarg);
return 1;
case LONG_ARGS_LOGGER:
uwsgi.log_master = 1;
uwsgi.master_process = 1;
uwsgi.requested_logger = uwsgi_str(optarg);
return 1;
case LONG_ARGS_LOG_SYSLOG:
log_syslog(optarg);
uwsgi.log_syslog = 1;
uwsgi.log_master = 1;
uwsgi.master_process = 1;
if (optarg) {
uwsgi.requested_logger = uwsgi_concat2("syslog:", optarg);
}
else {
uwsgi.requested_logger = "syslog";
}
return 1;
#ifdef UWSGI_ZEROMQ
case LONG_ARGS_LOG_ZEROMQ:
log_zeromq(optarg);
uwsgi.log_master = 1;
uwsgi.master_process = 1;
uwsgi.requested_logger = uwsgi_concat2("zeromq:", optarg);
return 1;
#endif
case LONG_ARGS_PRINT:
@@ -3219,6 +3326,11 @@ static int manage_base_opt(int i, char *optarg) {
case LONG_ARGS_CAP:
uwsgi_build_cap(optarg);
return 1;
#endif
#ifdef __linux__
case LONG_ARGS_UNSHARE:
uwsgi_build_unshare(optarg);
return 1;
#endif
case LONG_ARGS_BINARY_PATH:
uwsgi.binary_path = optarg;
@@ -3281,6 +3393,7 @@ static int manage_base_opt(int i, char *optarg) {
uct->filename = optarg;
uct->next = NULL;
uct->applied = 0;
return 1;
case LONG_ARGS_VASSAL_SOS_BACKLOG:
@@ -3339,6 +3452,12 @@ static int manage_base_opt(int i, char *optarg) {
}
uc->command = optarg+i;
return 1;
case LONG_ARGS_STATIC_SKIP_EXT:
uwsgi_string_new_list(&uwsgi.static_skip_ext, optarg);
return 1;
case LONG_ARGS_STATIC_INDEX:
uwsgi_string_new_list(&uwsgi.static_index, optarg);
return 1;
case LONG_ARGS_STATIC_MAP:
mountpoint = uwsgi_str(optarg);
docroot = strchr(mountpoint, '=');
@@ -3428,6 +3547,12 @@ static int manage_base_opt(int i, char *optarg) {
uwsgi_string_new_list(&uwsgi.touch_reload, optarg);
uwsgi.master_process = 1;
return 1;
case LONG_ARGS_EXEC_AS_ROOT:
uwsgi_string_new_list(&uwsgi.exec_as_root, optarg);
return 1;
case LONG_ARGS_EXEC_AS_USER:
uwsgi_string_new_list(&uwsgi.exec_as_user, optarg);
return 1;
case LONG_ARGS_PRIO:
uwsgi.prio = (int) strtol(optarg, NULL, 10);
return 1;
@@ -3597,12 +3722,18 @@ static int manage_base_opt(int i, char *optarg) {
#endif
case 'd':
if (!uwsgi.is_a_reload) {
daemonize(optarg);
}
else if (uwsgi.log_reopen) {
// do not daemonize in emperor mode
if (uwsgi.has_emperor) {
logto(optarg);
}
else {
if (!uwsgi.is_a_reload) {
daemonize(optarg);
}
else if (uwsgi.log_reopen) {
logto(optarg);
}
}
return 1;
case 's':
uwsgi_sock = uwsgi_new_socket(generate_socket_name(optarg));
+74 -22
View File
@@ -11,6 +11,8 @@ extern "C" {
#define UMAX64_STR "18446744073709551616"
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_log_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log(x);
#define uwsgi_error_safe(x) if (uwsgi.original_log_fd != 2) dup2(uwsgi.original_log_fd, 2) ; uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
#define uwsgi_log_initial if (!uwsgi.no_initial_output) uwsgi_log
#define uwsgi_fatal_error(x) uwsgi_error(x); exit(1);
#define uwsgi_error_open(x) uwsgi_log("open(\"%s\"): %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
@@ -65,6 +67,8 @@ extern char UWSGI_EMBED_CONFIG_END;
#define ULEP(pname)\
if (pname##_plugin.request) {\
uwsgi.p[pname##_plugin.modifier1] = &pname##_plugin;\
if (uwsgi.p[pname##_plugin.modifier1]->on_load)\
uwsgi.p[pname##_plugin.modifier1]->on_load();\
}\
else {\
if (uwsgi.gp_cnt >= MAX_GENERIC_PLUGINS) {\
@@ -72,6 +76,8 @@ extern char UWSGI_EMBED_CONFIG_END;
exit(1);\
}\
uwsgi.gp[uwsgi.gp_cnt] = &pname##_plugin;\
if (uwsgi.gp[uwsgi.gp_cnt]->on_load)\
uwsgi.gp[uwsgi.gp_cnt]->on_load();\
uwsgi.gp_cnt++;\
}\
@@ -126,8 +132,6 @@ extern char UWSGI_EMBED_CONFIG_END;
#include <sys/time.h>
#include <unistd.h>
#include <syslog.h>
#ifdef UWSGI_HAS_IFADDRS
#include <ifaddrs.h>
#endif
@@ -271,6 +275,7 @@ struct uwsgi_help_item {
struct uwsgi_config_template {
char *filename;
int applied;
struct uwsgi_config_template *next;
};
@@ -340,6 +345,19 @@ struct uwsgi_daemon {
struct uwsgi_daemon *next;
};
struct uwsgi_logger {
char *name;
ssize_t (*func)(struct uwsgi_logger *, char *, size_t);
int configured;
int fd;
void *data;
union uwsgi_sockaddr addr;
socklen_t addr_len;
int count;
struct msghdr msg;
struct uwsgi_logger *next;
};
struct uwsgi_queue_header {
uint64_t pos;
uint64_t pull_pos;
@@ -535,6 +553,13 @@ struct uwsgi_opt {
#define LONG_ARGS_LOGFILE_CHMOD 17165
#define LONG_ARGS_SUBSCRIBE_FREQ 17166
#define LONG_ARGS_SUBSCR_TOLERANCE 17167
#define LONG_ARGS_UNSHARE 17168
#define LONG_ARGS_EXEC_AS_ROOT 17169
#define LONG_ARGS_EXEC_AS_USER 17170
#define LONG_ARGS_STATIC_SKIP_EXT 17171
#define LONG_ARGS_LOGGER 17172
#define LONG_ARGS_STATIC_INDEX 17173
#define LONG_ARGS_CHEAPER_STEP 17174
#define UWSGI_OK 0
@@ -645,6 +670,7 @@ struct uwsgi_plugin {
const char *alias;
uint8_t modifier1;
void *data;
void (*on_load) (void);
int (*init) (void);
void (*post_init) (void);
void (*post_fork) (void);
@@ -656,6 +682,7 @@ struct uwsgi_plugin {
int (*request) (struct wsgi_request *);
void (*after_request) (struct wsgi_request *);
void (*init_apps) (void);
void (*preinit_apps) (void);
void (*fixup) (void);
void (*master_fixup) (int);
void (*master_cycle) (void);
@@ -677,7 +704,7 @@ struct uwsgi_plugin {
int (*spooler) (char *, char *, uint16_t, char *, size_t);
uint16_t(*rpc) (void *, uint8_t, char **, char *);
uint16_t(*rpc) (void *, uint8_t, char **, uint16_t *, char *);
void (*jail) (int (*)(void *), char **);
@@ -1059,6 +1086,7 @@ struct uwsgi_server {
int cheap;
// enable cheaper mode
int cheaper;
int cheaper_step;
// minimal number of running workers in cheaper mode
int cheaper_count;
// enable idle mode
@@ -1142,6 +1170,10 @@ struct uwsgi_server {
int cap_count;
#endif
#ifdef __linux__
int unshare;
#endif
// still working on it
char *profiler;
@@ -1175,15 +1207,8 @@ struct uwsgi_server {
off_t log_maxsize;
char *log_backupname;
int log_syslog;
int original_log_fd;
int log_socket;
int log_socket_fd;
union uwsgi_sockaddr *log_socket_addr;
socklen_t log_socket_size;
// static file serving
int file_serve_mode;
int build_mime_dict;
@@ -1191,12 +1216,23 @@ struct uwsgi_server {
struct uwsgi_probe *probes;
struct uwsgi_string_list *exec_as_root;
struct uwsgi_string_list *exec_as_user;
struct uwsgi_logger *loggers;
struct uwsgi_logger *choosen_logger;
char *requested_logger;
char *choosen_logger_arg;
int threaded_logger;
struct uwsgi_daemon *daemons;
int daemons_cnt;
struct uwsgi_dyn_dict *static_maps;
struct uwsgi_dyn_dict *check_static;
struct uwsgi_dyn_dict *mimetypes;
struct uwsgi_string_list *static_skip_ext;
struct uwsgi_string_list *static_index;
char *logfile;
int logfile_chown;
@@ -1323,6 +1359,7 @@ struct uwsgi_server {
#ifdef UWSGI_THREADING
// avoid thundering herd in threaded modes
pthread_mutex_t six_feet_under_lock;
pthread_mutex_t lock_static;
#endif
@@ -1442,7 +1479,6 @@ struct uwsgi_server {
int zeromq_recv_flag;
pthread_mutex_t zmq_lock;
pthread_key_t zmq_pull;
void *zmq_log_socket;
#endif
struct uwsgi_socket *sockets;
struct uwsgi_socket *shared_sockets;
@@ -1554,6 +1590,11 @@ struct uwsgi_server {
#ifdef __linux__
#ifdef MADV_MERGEABLE
int linux_ksm;
int ksm_buffer_size;
char *ksm_mappings_last;
char *ksm_mappings_current;
size_t ksm_mappings_last_size;
size_t ksm_mappings_current_size;
#endif
#endif
@@ -1573,6 +1614,7 @@ struct uwsgi_lb_group {
struct uwsgi_signal_entry {
int wid;
uint8_t modifier1;
char receiver[64];
void *handler;
@@ -1701,7 +1743,7 @@ struct uwsgi_shared {
#ifdef __linux__
struct tcp_info ti;
#endif
uint64_t load;
struct uwsgi_cron cron[MAX_CRONS];
int cron_cnt;
};
@@ -2096,13 +2138,13 @@ void uwsgi_route_signal(uint8_t);
int uwsgi_start(void *);
int uwsgi_register_rpc(char *, uint8_t, uint8_t, void *);
uint16_t uwsgi_rpc(char *, uint8_t, char **, char *);
uint16_t uwsgi_rpc(char *, uint8_t, char **, uint16_t *, char *);
char *uwsgi_do_rpc(char *, char *, uint8_t, char **, uint16_t *, uint16_t *);
char *uwsgi_cheap_string(char *, int);
int uwsgi_parse_array(char *, uint16_t, char **, uint8_t *);
int uwsgi_parse_array(char *, uint16_t, char **, uint16_t *, uint8_t *);
void log_syslog(char *);
struct uwsgi_gateway *register_gateway(char *, void (*)(void));
struct uwsgi_gateway *register_fat_gateway(char *, void (*)(void));
@@ -2210,6 +2252,9 @@ struct uwsgi_subscribe_req {
uint8_t modifier1;
uint8_t modifier2;
uint64_t cores;
uint64_t load;
};
#ifndef _NO_UWSGI_RB
@@ -2316,7 +2361,7 @@ uint16_t proto_base_add_uwsgi_header(struct wsgi_request *, char *, uint16_t, ch
uint16_t proto_base_add_uwsgi_var(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
#ifdef UWSGI_ZEROMQ
void log_zeromq(char *);
ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *, char *, size_t len);
int uwsgi_proto_zeromq_accept(struct wsgi_request *, int);
void uwsgi_proto_zeromq_close(struct wsgi_request *);
ssize_t uwsgi_proto_zeromq_writev_header(struct wsgi_request *, struct iovec *, size_t);
@@ -2362,9 +2407,7 @@ void uwsgi_ignition(void);
void master_check_cluster_nodes(void);
int uwsgi_respawn_worker(int);
void log_socket(char *);
socklen_t socket_to_in_addr(char *, char *, struct sockaddr_in *);
socklen_t socket_to_in_addr(char *, char *, int, struct sockaddr_in *);
socklen_t socket_to_un_addr(char *, struct sockaddr_un *);
int uwsgi_get_shared_socket_fd_by_num(int);
@@ -2395,8 +2438,6 @@ int uwsgi_signal_registered(uint8_t);
int uwsgi_endswith(char *, char *);
char *uwsgi_get_var(struct wsgi_request *, char *, uint16_t *);
int uwsgi_cache_server(char *, int);
void uwsgi_chown(char *, char *);
@@ -2453,6 +2494,9 @@ struct uwsgi_subscribe_node {
int death_mark;
uint64_t reference;
uint64_t cores;
uint64_t load;
uint64_t failcnt;
struct uwsgi_subscribe_slot *slot;
@@ -2503,7 +2547,7 @@ void manage_cluster_announce(char *, uint16_t, char *, uint16_t, void *);
int uwsgi_read_response(int, struct uwsgi_header *, int, char **);
char *uwsgi_simple_file_read(char *);
void uwsgi_send_subscription(char *, char *, size_t , char *, size_t, uint8_t);
void uwsgi_send_subscription(char *, char *, size_t , uint8_t, uint8_t , uint8_t);
void uwsgi_subscribe(char *, uint8_t);
@@ -2513,8 +2557,10 @@ struct uwsgi_probe *uwsgi_probe_register(struct uwsgi_probe **, char *, int (*)(
int uwsgi_add_probe(uint8_t sig, char *, char *, int, int);
int uwsgi_is_bad_connection(int);
int uwsgi_long2str2n(unsigned long long, char *, int);
#ifdef __linux__
void uwsgi_build_unshare(char *);
#ifdef MADV_MERGEABLE
void uwsgi_linux_ksm_map(void);
#endif
@@ -2524,6 +2570,12 @@ void uwsgi_linux_ksm_map(void);
void uwsgi_build_cap(char *);
#endif
void uwsgi_register_logger(char *, ssize_t (*func)(struct uwsgi_logger *, char *, size_t));
struct uwsgi_logger *uwsgi_get_logger(char *);
char *uwsgi_getsockname(int);
char *uwsgi_get_var(struct wsgi_request *, char *, uint16_t, uint16_t *);
#ifdef UWSGI_AS_SHARED_LIBRARY
int uwsgi_init(int, char **, char **);
#endif
+29 -14
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.0-dev'
uwsgi_version = '1.0'
import os
import re
@@ -105,7 +105,7 @@ def compile(cflags, objfile, srcfile):
sys.exit(1)
def build_uwsgi(uc):
def build_uwsgi(uc, print_only=False):
gcc_list, cflags, ldflags, libs = uc.get_gcll()
@@ -126,6 +126,10 @@ def build_uwsgi(uc):
cflags.append(epc)
cflags.append(eplc)
if print_only:
print(' '.join(cflags))
sys.exit(0)
print("configured CFLAGS: %s" % ' '.join(cflags))
print("*** uWSGI compiling server core ***")
@@ -220,9 +224,10 @@ def build_uwsgi(uc):
class uConf(object):
def __init__(self, filename):
def __init__(self, filename, mute=False):
self.config = ConfigParser.ConfigParser()
print("using profile: %s" % filename)
if not mute:
print("using profile: %s" % filename)
if not os.path.exists(filename):
raise Exception("profile not found !!!")
@@ -254,7 +259,7 @@ class uConf(object):
self.gcc_list.append('lib/netlink')
try:
lk_ver = uwsgi_os_k.split('.')
if int(lk_ver[0]) <= 2 and int(lk_ver[1]) <= 6 and int(lk_ver[2]):
if int(lk_ver[0]) <= 2 and int(lk_ver[1]) <= 6 and int(lk_ver[2]) <= 9:
self.cflags.append('-DOBSOLETE_LINUX_KERNEL')
except:
pass
@@ -281,8 +286,8 @@ class uConf(object):
except:
self.include_path = ['/usr/include', '/usr/local/include']
print("detected include path: %s" % self.include_path)
if not mute:
print("detected include path: %s" % self.include_path)
try:
gcc_major = int(gcc_version.split('.')[0])
@@ -809,6 +814,11 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
except:
pass
try:
p_cflags.remove('-Winline')
except:
pass
#for ofile in up.OBJ_LIST:
# gcc_list.insert(0,ofile)
@@ -829,13 +839,7 @@ if __name__ == "__main__":
print("please specify an argument")
sys.exit(1)
if cmd == '--cflags':
print(' '.join(cflags))
if cmd == '--ldflags':
print(' '.join(ldflags))
if cmd == '--libs':
print(' '.join(libs))
elif cmd == '--build':
if cmd == '--build':
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
try:
bconf = sys.argv[2]
@@ -846,6 +850,17 @@ if __name__ == "__main__":
if not '/' in bconf:
bconf = 'buildconf/%s' % bconf
build_uwsgi(uConf(bconf))
elif cmd == '--cflags':
bconf = os.environ.get('UWSGI_PROFILE','default.ini')
try:
bconf = sys.argv[2]
except:
pass
if not bconf.endswith('.ini'):
bconf += '.ini'
if not '/' in bconf:
bconf = 'buildconf/%s' % bconf
build_uwsgi(uConf(bconf, True), True)
elif cmd == '--unbit':
build_uwsgi(uConf('buildconf/unbit.ini'))
elif cmd == '--plugin':
+39 -24
View File
@@ -8,15 +8,14 @@ except:
if uwsgi.masterpid() == 0:
raise Exception("you have to enable the uWSGI master process to use this module")
if uwsgi.opt.get('lazy'):
raise Exception("uWSGI lazy mode is not supported by this module")
raise Exception(
"you have to enable the uWSGI master process to use this module")
spooler_functions = {}
mule_functions = {}
postfork_chain = []
def get_free_signal():
for signum in xrange(0, 256):
if not uwsgi.signal_registered(signum):
@@ -24,12 +23,14 @@ def get_free_signal():
raise Exception("No free uwsgi signal available")
def manage_spool_request(vars):
ret = spooler_functions[vars['ud_spool_func']](vars)
if not vars.has_key('ud_spool_ret'):
if not 'ud_spool_ret' in vars:
return ret
return int(vars['ud_spool_ret'])
def postfork_chain_hook():
for f in postfork_chain:
f()
@@ -37,10 +38,12 @@ def postfork_chain_hook():
uwsgi.spooler = manage_spool_request
uwsgi.post_fork_hook = postfork_chain_hook
class postfork(object):
def __init__(self, f):
postfork_chain.append(f)
class spool(object):
def spool(self, *args, **kwargs):
@@ -53,12 +56,14 @@ class spool(object):
return uwsgi.spool(arguments)
def __init__(self, f):
if not uwsgi.opt.has_key('spooler'):
raise Exception("you have to enable the uWSGI spooler to use the @spool decorator")
if not 'spooler' in uwsgi.opt:
raise Exception(
"you have to enable the uWSGI spooler to use @spool decorator")
self.f = f
spooler_functions[f.__name__] = self.f
self.f.spool = self.spool
self.base_dict = {'ud_spool_func':self.f.__name__}
self.base_dict = {'ud_spool_func': self.f.__name__}
class spoolforever(spool):
@@ -71,6 +76,7 @@ class spoolforever(spool):
arguments.update(kwargs)
return uwsgi.spool(arguments)
class spoolraw(spool):
def spool(self, *args, **kwargs):
@@ -97,15 +103,13 @@ class mulefunc(object):
uwsgi.mule_msg(pickle.dumps(
{
'service': 'uwsgi_mulefunc',
'func':self.fname,
'func': self.fname,
'args': args,
'kwargs': kwargs
}
), self.mule)
def __call__(self, *args, **kwargs):
if not self.fname:
self.fname = args[0].__name__
mule_functions[self.fname] = args[0]
@@ -117,7 +121,7 @@ class mulefunc(object):
def mule_msg_dispatcher(message):
msg = pickle.loads(message)
if msg['service'] == 'uwsgi_mulefunc':
return mule_functions[msg['func']](*msg['args'],**msg['kwargs'])
return mule_functions[msg['func']](*msg['args'], **msg['kwargs'])
uwsgi.mule_msg_hook = mule_msg_dispatcher
@@ -131,12 +135,13 @@ class rpc(object):
uwsgi.register_rpc(self.name, f)
return f
class farm_loop(object):
def __init__(self, f, farm):
self.f = f
self.farm = farm
def __call__(self):
if uwsgi.mule_id() == 0:
return
@@ -147,6 +152,7 @@ class farm_loop(object):
if message:
self.f(message)
class farm(object):
def __init__(self, name=None, **kwargs):
@@ -155,6 +161,7 @@ class farm(object):
def __call__(self, f):
postfork_chain.append(farm_loop(f, self.name))
class mule_brain(object):
def __init__(self, f, num):
@@ -165,13 +172,14 @@ class mule_brain(object):
if uwsgi.mule_id() == self.num:
self.f()
class mule_brainloop(mule_brain):
def __call__(self):
if uwsgi.mule_id() == self.num:
while True:
self.f()
class mule(object):
def __init__(self, num):
@@ -180,10 +188,12 @@ class mule(object):
def __call__(self, f):
postfork_chain.append(mule_brain(f, self.num))
class muleloop(mule):
def __call__(self, f):
postfork_chain.append(mule_brainloop(f, self.num))
class mulemsg_loop(object):
def __init__(self, f, num):
@@ -192,12 +202,12 @@ class mulemsg_loop(object):
def __call__(self):
if uwsgi.mule_id() == self.num:
print " i am the mule"
while True:
message = uwsgi.mule_get_msg()
if message:
self.f(message)
class mulemsg(object):
def __init__(self, num):
self.num = num
@@ -205,28 +215,31 @@ class mulemsg(object):
def __call__(self, f):
postfork_chain.append(mulemsg_loop(f, self.num))
class signal(object):
def __init__(self, num, **kwargs):
self.num = num
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
return f
class timer(object):
def __init__(self, secs, **kwargs):
self.num = kwargs.get('signum', get_free_signal())
self.secs = secs
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
uwsgi.add_timer(self.num, self.secs)
return f
class cron(object):
def __init__(self, minute, hour, day, month, dayweek, **kwargs):
@@ -236,39 +249,41 @@ class cron(object):
self.day = day
self.month = month
self.dayweek = dayweek
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
uwsgi.add_cron(self.num, self.minute, self.hour, self.day, self.month, self.dayweek)
uwsgi.add_cron(self.num, self.minute, self.hour,
self.day, self.month, self.dayweek)
return f
class rbtimer(object):
def __init__(self, secs, **kwargs):
self.num = kwargs.get('signum', get_free_signal())
self.secs = secs
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
uwsgi.add_rb_timer(self.num, self.secs)
return f
class filemon(object):
def __init__(self, fsobj, **kwargs):
self.num = kwargs.get('signum', get_free_signal())
self.fsobj = fsobj
self.target = kwargs.get('target', '')
self.target = kwargs.get('target', '')
def __call__(self, f):
uwsgi.register_signal(self.num, self.target, f)
uwsgi.add_file_monitor(self.num, self.fsobj)
return f
class erlang(object):
def __init__(self, name):
@@ -278,6 +293,7 @@ class erlang(object):
uwsgi.erlang_register_process(self.name, f)
return f
class lock(object):
def __init__(self, f):
self.f = f
@@ -292,6 +308,7 @@ class lock(object):
finally:
uwsgi.unlock()
class thread(object):
def __init__(self, f):
@@ -302,5 +319,3 @@ class thread(object):
t.daemon = True
t.start()
return self.f
+18
View File
@@ -14,6 +14,7 @@ end
$postfork_chain = []
$mulefunc_list = []
$spoolfunc_list = []
module UWSGI
module_function
@@ -21,6 +22,11 @@ module UWSGI
$postfork_chain.each {|func| func.call }
end
module_function
def spooler(args)
$spoolfunc_list[args['ud_spool_func'].to_i].call(args)
end
module_function
def mule_msg_hook(message)
service = Marshal.load(message)
@@ -62,6 +68,18 @@ def postfork(&block)
$postfork_chain << block
end
class SpoolProc < Proc
def initialize(&block)
@block = block
@id = (($spoolfunc_list << block).length-1).to_s
end
def call(args)
args['ud_spool_func'] = @id
UWSGI::send_to_spooler(args)
end
end
def rpc(name, &block)
if block.arity <= 0
UWSGI.register_rpc(name, block, 0)
+4 -4
View File
@@ -30,12 +30,12 @@ def serve_logo(e, sr):
def serve_options(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in xrange(0,256):
yield "%d = %d<br/>" % (opt, uwsgi.get_option(opt))
yield "<b>%d</b> = %d<br/>" % (opt, uwsgi.get_option(opt))
def serve_config(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in uwsgi.opt.keys():
yield "%s = %s<br/>" % (opt, uwsgi.opt[opt])
yield "<b>%s</b> = %s<br/>" % (opt, uwsgi.opt[opt])
routes = {}
routes['/xsendfile'] = xsendfile
@@ -95,7 +95,7 @@ def application(env, start_response):
""" % (w['id'], w['pid'], w['status'], w['running_time']/1000, w['avg_rt']/1000, w['tx'], apps)
return """
<img src="/logo"/> version %s<br/>
<img src="/logo"/> version %s running on %s<br/>
<hr size="1"/>
Configuration<br/>
@@ -115,7 +115,7 @@ Workers and applications<br/>
%s
</table>
""" % (uwsgi.version, workers)
""" % (uwsgi.version, uwsgi.hostname, workers)
+12
View File
@@ -154,6 +154,10 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
case YAML_VALUE_TOKEN:
status = 2;
break;
case YAML_FLOW_SEQUENCE_START_TOKEN:
case YAML_BLOCK_SEQUENCE_START_TOKEN:
status = 3;
break;
case YAML_BLOCK_MAPPING_START_TOKEN:
if (!in_uwsgi_section) {
if (key) {
@@ -170,6 +174,8 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
}
break;
case YAML_SCALAR_TOKEN:
case YAML_FLOW_ENTRY_TOKEN:
case YAML_BLOCK_ENTRY_TOKEN:
if (status == 1) {
key = (char *) token.data.scalar.value;
}
@@ -180,6 +186,12 @@ void uwsgi_yaml_config(char *file, char *magic_table[]) {
}
status = 0;
}
else if (status == 3) {
val = (char *) token.data.scalar.value;
if (key && val && in_uwsgi_section) {
add_exported_option(key, val, 0);
}
}
else {
uwsgi_log("unsupported YAML token in %s block\n", section_asked);
parsing = 0;