Compare commits

..
25 Commits
Author SHA1 Message Date
roberto@natty32 9746759c68 fixed changelog before official release 2011-03-26 09:39:53 +01:00
roberto@natty32 170ee2b98a date was wrong in 0.9.7.1 2011-03-26 09:38:21 +01:00
roberto@natty32 938fb777dd uWSGI 0.9.7.1 2011-03-26 09:36:11 +01:00
roberto@natty32 33e1aafcd1 Added tag 0.9.7.1 for changeset d9b9b540f7dc 2011-03-26 09:35:31 +01:00
roberto@natty32 597ee90041 add sys.abiflags if necessary 2011-03-26 09:27:30 +01:00
roberto@natty32 e87e54ea28 allow --namespace-net and fix python library name 2011-03-26 09:18:52 +01:00
roberto@natty32 5c64c1ac3f fixed post-buffering without pep3333-input 2011-03-25 19:11:53 +01:00
roberto@natty32 c611cbc2ca fixed current_wsgi_req in multithreading without cores 2011-03-23 11:59:05 +01:00
roberto@sirius 9d051f4171 fixed a buf on older OSX versions (i hope) 2011-03-22 19:34:12 +01:00
roberto@sirius 6aee788678 fixed cmsg parsing 2011-03-22 17:21:19 +01:00
roberto@natty32 425a45caa7 updated banner message in debug mode 2011-03-22 17:02:20 +01:00
roberto@natty32 0571601e02 added --map-socket 2011-03-22 14:55:54 +01:00
roberto@natty32 c1992c8c7a added --check-cache 2011-03-22 12:12:03 +01:00
roberto@natty32 bd913870c7 fixed setup.py 2011-03-21 10:36:52 +01:00
roberto@natty32 7a479dd47f add 304/If-Modified-Since support for --check-static <dir> 2011-03-21 10:31:50 +01:00
roberto@natty32 7ae77aa58d added UWSGI_CACHE_GET dynamic variable 2011-03-20 21:24:32 +01:00
roberto@natty32 97a4260d44 added --pidfile2 and --logfile-chown 2011-03-20 08:05:27 +01:00
roberto@mrspurr b90d711764 allow python modules to be on http server 2011-03-20 07:51:56 +01:00
roberto@mrspurr 22de5b523e reintroduce modifier1 30 2011-03-19 17:03:00 +01:00
roberto@mrspurr 5798b824c0 forbid daemonizing in vassal mode 2011-03-19 11:03:16 +01:00
roberto@goyle 4cbf6cfc33 various fixes in touch_reload 2011-03-19 09:33:28 +01:00
roberto@mrspurr 8b55460156 added persistence for queue 2011-03-18 20:20:36 +01:00
roberto@mrspurr a61d48a451 fixed stackless support 2011-03-18 08:14:12 +01:00
roberto@mrspurr b9f4d57d67 applied activestate fix for --root support in setup.py 2011-03-18 07:15:10 +01:00
roberto@natty32 92cd36d14d ready for first stable release 2011-03-17 09:15:52 +01:00
26 changed files with 766 additions and 236 deletions
+4
View File
@@ -13,3 +13,7 @@ ef31fc61ac48018c464f28ebfdf865b96bf83f18 0.9.6.2
ff4111eb8f55b958ec91c70163e10f3372a9b94d 0.9.7-rc1
eb8aff2926230bb114fb90f67203440a2c534bf1 0.9.7-rc2
311eef929ec8fd0a5dc8c16531afb7bb42d36d01 0.9.7-rc3
4b50c04e414f1d9ab8b0b5910aba83d09ac21abb 0.9.7
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
+31
View File
@@ -1,5 +1,36 @@
*** march 2011 ***
* 0.9.7.1 [20110326]
- fixed python stackless support
- added persistence for queue
- forbid daemonizing in vassal mode
- modifier1 30 is available again
- allow python modules to be mapped/aliased via http
- added --pidfile2 and --logfile-chown
- added UWSGI_CACHE_GET dynamic variable
- 304/If-Modified-Since support for --check-static
- option --check-cache for integrated caching
- option --map-socket to assign specific workers to socket
- fixed unix fd passing on older OSX versions
- fixed post-buffering without pep3333-input
- fixed python threading without uwsgi cores
- support for Linux network namespace
- build with sys.abiflags if necessary
* 0.9.7 [20110317]
- fixed psgi compilation on GNU systems
- improved --pep3333-input
- better error reporting on failed open/fopen
- fixed uGreen
- added greenlet support
- various solaris fixes
- new help system
- updated async support
- fixed uwsgi.cache_get in python
* 0.9.7-rc3 [20110312]
- added support for persistent cache (--cache-store <filename>)
+1
View File
@@ -320,6 +320,7 @@ void *async_loop(void *arg1) {
uwsgi.wsgi_req = current_request->wsgi_req;
uwsgi.schedule_to_req();
uwsgi.wsgi_req->switches++;
next_async_request = current_request->next;
// request ended ?
+4
View File
@@ -0,0 +1,4 @@
[uwsgi]
inherit = default
plugin_dir = /usr/lib/uwsgi
embedded_plugins = null
+18 -23
View File
@@ -337,6 +337,12 @@ void master_loop(char **argv, char **environ) {
}
}
if (uwsgi.queue_store && uwsgi.queue_filesize) {
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
}
for (;;) {
//uwsgi_log("ready_to_reload %d %d\n", ready_to_reload, uwsgi.numproc);
@@ -950,6 +956,12 @@ void master_loop(char **argv, char **environ) {
}
}
if (uwsgi.queue_store && uwsgi.queue_filesize && uwsgi.queue_store_sync && ((master_cycles % uwsgi.queue_store_sync) == 0)) {
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
}
#endif
@@ -1040,7 +1052,9 @@ void master_loop(char **argv, char **environ) {
}
uwsgi_log( "DAMN ! process %d died :( trying respawn ...\n", diedpid);
if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
uwsgi_log( "DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int)diedpid);
}
gettimeofday(&last_respawn, NULL);
if (last_respawn.tv_sec == uwsgi.respawn_delta) {
uwsgi_log( "worker respawning too fast !!! i have to sleep a bit...\n");
@@ -1075,28 +1089,9 @@ void master_loop(char **argv, char **environ) {
uwsgi_error("fork()");
}
else {
uwsgi_log( "Respawned uWSGI worker (new pid: %d)\n", pid);
//close(uwsgi.workers[uwsgi.mywid].pipe[1]);
//event_queue_add_fd_read(uwsgi.master_queue, uwsgi.workers[uwsgi.mywid].pipe[0]);
#ifdef UWSGI_SPOOLER
if (uwsgi.mywid <= 0 && diedpid != uwsgi.shared->spooler_pid) {
#else
if (uwsgi.mywid <= 0) {
#endif
#ifdef UWSGI_PROXY
// TODO if no gateway span the error !!!
if (diedpid != uwsgi.shared->proxy_pid) {
#endif
uwsgi_log( "warning the died pid was not in the workers list. Probably you hit a BUG of uWSGI\n");
#ifdef UWSGI_PROXY
}
#endif
}
}
}
uwsgi_log( "Respawned uWSGI worker %d (new pid: %d)\n", uwsgi.mywid, (int) pid);
}
}
}
}
+18 -4
View File
@@ -1,13 +1,27 @@
[uwsgi]
; socket 0
socket = :3033
; socket 1
socket = :3034
vacuum = true
; socket 2
socket = pippo1.sock
; socket 3
socket = pippo2.sock
; socket 4
socket = 127.0.0.1:1717
map-socket = 0:1,2,3,4
map-socket = 1:4
map-socket = 2:10
map-socket = 3:5,6,9
map-socket = 4:7,8,9
vacuum = true
memory-report = true
master = true
processes = 10
mount = /app1=werkzeug.testapp:test_app
mount = /app2=config:/Users/roberta/uwsgi/my.ini
mount = /app3=pinaxsite/deploy/pinax.wsgi
;mount = /app1=werkzeug.testapp:test_app
;mount = /app2=config:/Users/roberta/uwsgi/my.ini
;mount = /app3=pinaxsite/deploy/pinax.wsgi
+6
View File
@@ -879,6 +879,11 @@ int http_init() {
return 0;
}
struct uwsgi_help_item http_help[] = {
{ "http-to <addr>", "forward http requests to uwsgi instance bound at <addr>"},
{ 0, 0 }
};
int http_opt(int i, char *optarg) {
@@ -931,6 +936,7 @@ struct uwsgi_plugin http_plugin = {
.options = http_options,
.manage_opt = http_opt,
.help = http_help,
.init = http_init,
};
+8
View File
@@ -149,6 +149,14 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
wi->interpreter = up.main_thread;
}
if (wsgi_req->touch_reload_len) {
struct stat trst;
char *touch_reload = uwsgi_strncopy(wsgi_req->touch_reload, wsgi_req->touch_reload_len);
if (!stat(touch_reload, &trst)) {
wi->touch_reload = touch_reload;
wi->touch_reload_mtime = trst.st_mtime;
}
}
wi->callable = up.loaders[loader](arg1);
+46 -24
View File
@@ -40,6 +40,9 @@ struct uwsgi_help_item uwsgi_python_help[] = {
{"module <module>" ,"name of python config module"},
{"optimize <n>", "set python optimization level to <n>"},
{"home <path>", "set python home/virtualenv"},
{"pyhome <path>", "set python home/virtualenv"},
{"virtualenv <path>", "set python home/virtualenv"},
{"venv <path>", "set python home/virtualenv"},
{"callable <callable>", "set the callable (default 'application')"},
{"paste <config:/egg:>", "load applications using paste.deploy.loadapp()"},
{"pythonpath <dir>", "add <dir> to PYTHONPATH"},
@@ -127,6 +130,9 @@ int uwsgi_python_init() {
uwsgi_log("Python main interpreter initialized at %p\n", up.main_thread);
// add the hacky modifier1 30
uwsgi.p[30]->request = uwsgi.p[0]->request;
return 1;
}
@@ -179,36 +185,52 @@ PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {
char *real_filename = filename;
pyfile = fopen(filename, "r");
if (!pyfile) {
uwsgi_log("failed to open python file %s\n", filename);
exit(1);
}
if (strncmp(filename, "http://", 7)) {
if (fstat(fileno(pyfile), &pystat)) {
uwsgi_error("fstat()");
exit(1);
}
if (S_ISDIR(pystat.st_mode)) {
is_a_package = 1;
fclose(pyfile);
real_filename = uwsgi_concat2(filename, "/__init__.py");
pyfile = fopen(real_filename, "r");
pyfile = fopen(filename, "r");
if (!pyfile) {
uwsgi_error_open(real_filename);
uwsgi_log("failed to open python file %s\n", filename);
exit(1);
}
}
py_file_node = PyParser_SimpleParseFile(pyfile, real_filename, Py_file_input);
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse file %s\n", real_filename);
exit(1);
}
if (fstat(fileno(pyfile), &pystat)) {
uwsgi_error("fstat()");
exit(1);
}
fclose(pyfile);
if (S_ISDIR(pystat.st_mode)) {
is_a_package = 1;
fclose(pyfile);
real_filename = uwsgi_concat2(filename, "/__init__.py");
pyfile = fopen(real_filename, "r");
if (!pyfile) {
uwsgi_error_open(real_filename);
exit(1);
}
}
py_file_node = PyParser_SimpleParseFile(pyfile, real_filename, Py_file_input);
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse file %s\n", real_filename);
exit(1);
}
fclose(pyfile);
}
else {
int pycontent_size = 0;
char *pycontent = uwsgi_open_and_read(filename, &pycontent_size, 1, NULL);
if (pycontent) {
py_file_node = PyParser_SimpleParseString(pycontent, Py_file_input);
if (!py_file_node) {
PyErr_Print();
uwsgi_log("failed to parse url %s\n", real_filename);
exit(1);
}
}
}
py_compiled_node = (PyObject *) PyNode_Compile(py_file_node, real_filename);
-1
View File
@@ -5,7 +5,6 @@ extern struct uwsgi_python up;
int manage_python_response(struct wsgi_request *wsgi_req) {
// use standard WSGI response parse
wsgi_req->switches++;
return uwsgi_response_subhandler_wsgi(wsgi_req);
}
+51 -2
View File
@@ -2528,7 +2528,6 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
}
if (uwsgi.queue_size) {
uwsgi_log("locking queue\n");
uwsgi_wlock(uwsgi.queue_lock);
if (uwsgi_queue_push(message, msglen)) {
Py_INCREF(Py_True);
@@ -2539,7 +2538,6 @@ PyObject *py_uwsgi_queue_push(PyObject * self, PyObject * args) {
res = Py_None;
}
uwsgi_rwunlock(uwsgi.queue_lock);
uwsgi_log("unlocked queue\n");
return res;
}
@@ -2611,6 +2609,56 @@ PyObject *py_uwsgi_queue_get(PyObject * self, PyObject * args) {
return Py_None;
}
PyObject *py_uwsgi_queue_last(PyObject * self, PyObject * args) {
long num = 0;
uint64_t size = 0;
char *message;
PyObject *res, *zero;
uint64_t base;
if (!PyArg_ParseTuple(args, "l:queue_last", &num)) {
return NULL;
}
if (uwsgi.queue_size) {
res = PyList_New(0);
uwsgi_rlock(uwsgi.queue_lock);
if (uwsgi.shared->queue_pos > 0) {
base = uwsgi.shared->queue_pos-1;
}
else {
base = uwsgi.queue_size-1;
}
if (num > (long)uwsgi.queue_size) num = uwsgi.queue_size;
while(num) {
message = uwsgi_queue_get(base, &size);
if (message && size) {
zero = PyString_FromStringAndSize(message, size);
PyList_Append(res, zero);
Py_DECREF(zero);
}
else {
uwsgi_rwunlock(uwsgi.queue_lock);
return res;
}
if (base > 0) {
base--;
}
else {
base = uwsgi.queue_size-1;
}
num--;
}
uwsgi_rwunlock(uwsgi.queue_lock);
return res;
}
Py_INCREF(Py_None);
return Py_None;
}
PyObject *py_uwsgi_cache_get(PyObject * self, PyObject * args) {
char *key;
@@ -2676,6 +2724,7 @@ static PyMethodDef uwsgi_cache_methods[] = {
static PyMethodDef uwsgi_queue_methods[] = {
{"queue_get", py_uwsgi_queue_get, METH_VARARGS, ""},
{"queue_last", py_uwsgi_queue_last, METH_VARARGS, ""},
{"queue_push", py_uwsgi_queue_push, METH_VARARGS, ""},
{"queue_pull", py_uwsgi_queue_pull, METH_VARARGS, ""},
{"queue_slot", py_uwsgi_queue_slot, METH_VARARGS, ""},
+6 -4
View File
@@ -20,10 +20,12 @@ else:
os.environ['LD_RUN_PATH'] = "%s/lib" % sysconfig.PREFIX
version = sys.version_info
uver = "%d.%d" % (version[0], version[1])
LIBS.append('-lpython' + uver)
version = sysconfig.get_config_var('VERSION')
try:
version = version + sys.abiflags
except:
pass
LIBS.append('-lpython' + version)
#if str(PYLIB_PATH) != '':
# libs.insert(0,'-L' + PYLIB_PATH)
+8 -2
View File
@@ -262,7 +262,6 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
}
if (uwsgi_parse_vars(wsgi_req)) {
uwsgi_log("Invalid WSGI request. skip.\n");
return -1;
}
@@ -429,6 +428,9 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
goto clear;
}
}
else {
wsgi_req->async_post = fdopen(wsgi_req->poll.fd, "r");
}
}
else {
// read to disk if post_cl > post_buffering
@@ -472,11 +474,15 @@ int uwsgi_request_wsgi(struct wsgi_request *wsgi_req) {
while (wi->response_subhandler(wsgi_req) != UWSGI_OK) {
wsgi_req->switches++;
#ifdef UWSGI_ASYNC
if (uwsgi.async > 1) {
return UWSGI_AGAIN;
}
else {
#endif
wsgi_req->switches++;
#ifdef UWSGI_ASYNC
}
#endif
}
+2 -2
View File
@@ -68,7 +68,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[2].iov_len = PyString_Size(head);
#endif
uh.pktsize += wsgi_req->hvec[2].iov_len;
wsgi_req->status = atoi(wsgi_req->hvec[2].iov_base);
wsgi_req->status = uwsgi_str3_num(wsgi_req->hvec[2].iov_base);
wsgi_req->hvec[3].iov_base = nl;
wsgi_req->hvec[3].iov_len = NL_SIZE;
uh.pktsize += wsgi_req->hvec[3].iov_len;
@@ -87,7 +87,7 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[1].iov_len = PyString_Size(head);
#endif
uh.pktsize += wsgi_req->hvec[1].iov_len;
wsgi_req->status = atoi(wsgi_req->hvec[1].iov_base);
wsgi_req->status = uwsgi_str3_num(wsgi_req->hvec[1].iov_base);
wsgi_req->hvec[2].iov_base = nl;
wsgi_req->hvec[2].iov_len = NL_SIZE;
uh.pktsize += wsgi_req->hvec[2].iov_len;
-3
View File
@@ -94,14 +94,12 @@ VALUE protected_fiber_loop() {
if (!wsgi_req) goto cycle;
uwsgi_log("request passed to fiber core %d\n", wsgi_req->async_id);
uwsgi.wsgi_req = wsgi_req;
uwsgi.wsgi_req->switches++;
rb_fiber_resume(fiber_list[wsgi_req->async_id], 0, NULL);
}
else {
wsgi_req = find_wsgi_req_by_fd((int)uwsgi.async_events[i].ASYNC_FD, -1);
if (wsgi_req) {
uwsgi.wsgi_req = wsgi_req;
uwsgi.wsgi_req->switches++;
rb_fiber_resume(fiber_list[wsgi_req->async_id], 0, NULL);
}
else {
@@ -116,7 +114,6 @@ cycle:
//uwsgi_log("resuming fiber %d %p\n", current, fiber_list[current]);
uwsgi.wsgi_req = uwsgi.wsgi_requests[current];
uwsgi.wsgi_req->switches++;
if (uwsgi.wsgi_req->async_status != UWSGI_ACCEPTING) {
uwsgi_log("passing control to fiber %d\n", current);
rb_fiber_resume(fiber_list[current], 0, NULL);
+84
View File
@@ -0,0 +1,84 @@
#include "../python/uwsgi_python.h"
#include <stackless_api.h>
extern struct uwsgi_server uwsgi;
struct ustackless {
int enabled;
PyObject *callable;
PyTaskletObject **sl;
} usl;
struct option stackless_options[] = {
{"stackless", no_argument, &usl.enabled, 1},
{ 0, 0, 0, 0 }
};
PyObject *py_uwsgi_stackless_request(PyObject * self, PyObject *args) {
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh.modifier1]->request(uwsgi.wsgi_req);
uwsgi.wsgi_req->suspended = 0;
Py_DECREF(usl.sl[uwsgi.wsgi_req->async_id]);
Py_INCREF(Py_None);
return Py_None;
}
PyMethodDef uwsgi_stackless_request_method[] = {{"uwsgi_stackless_request", py_uwsgi_stackless_request, METH_VARARGS, ""}};
inline static void stackless_schedule_to_req() {
int id = uwsgi.wsgi_req->async_id;
if (!uwsgi.wsgi_req->suspended) {
usl.sl[id] = PyTasklet_New(NULL, usl.callable);
PyObject *args = PyTuple_New(0);
PyTasklet_Setup(usl.sl[id], args, NULL);
Py_DECREF(args);
uwsgi.wsgi_req->suspended = 1;
}
PyTasklet_Run(usl.sl[id]);
if (uwsgi.wsgi_req->suspended) {
uwsgi.wsgi_req->async_status = UWSGI_AGAIN;
}
}
inline static void stackless_schedule_to_main(struct wsgi_request *wsgi_req) {
PyStackless_Schedule(Py_None, 1);
uwsgi.wsgi_req = wsgi_req;
}
int stackless_init() {
return 0;
}
void stackless_init_apps(void) {
if (!usl.enabled) {
return;
}
usl.sl = uwsgi_malloc( sizeof(PyTaskletObject *) * uwsgi.async );
usl.callable = PyCFunction_New(uwsgi_stackless_request_method, NULL);
uwsgi_log("enabled stackless engine\n");
uwsgi.schedule_to_main = stackless_schedule_to_main;
uwsgi.schedule_to_req = stackless_schedule_to_req;
return;
}
struct uwsgi_plugin stackless_plugin = {
.name = "stackless",
.init = stackless_init,
.init_apps = stackless_init_apps,
.options = stackless_options,
};
+8
View File
@@ -0,0 +1,8 @@
from distutils import sysconfig
NAME='stackless'
CFLAGS = ['-I' + sysconfig.get_python_inc(), '-I' + sysconfig.get_python_inc(plat_specific=True)]
LDFLAGS = []
LIBS = []
GCC_LIST = ['stackless']
+177 -9
View File
@@ -16,6 +16,112 @@ static size_t get_content_length(char *buf, uint16_t size) {
return val;
}
void set_http_date(time_t t, char *dst) {
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
static char *months[] = {
"Jan", "Feb", "Mar", "Apr",
"May", "Jun", "Jul", "Aug",
"Sep", "Oct", "Nov", "Dec"
};
struct tm *hdtm = gmtime(&t);
snprintf(dst, 49, "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n\r\n",
week[hdtm->tm_wday], hdtm->tm_mday,
months[hdtm->tm_mon], hdtm->tm_year+1900,
hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
}
// only RFC 1123 is supported
time_t parse_http_date(char *date, uint16_t len) {
struct tm hdtm;
if (len != 29 && date[3] != ',') return 0;
hdtm.tm_mday = uwsgi_str2_num(date+5);
switch(date[8]) {
case 'J':
if (date[9] == 'a') {
hdtm.tm_mon = 0;
break;
}
if (date[9] == 'u') {
if (date[10] == 'n') {
hdtm.tm_mon = 5;
break;
}
if (date[10] == 'l') {
hdtm.tm_mon = 6;
break;
}
return 0;
}
return 0;
case 'F':
hdtm.tm_mon = 1;
break;
case 'M':
if (date[9] != 'a') return 0;
if (date[10] == 'r') {
hdtm.tm_mon = 2;
break;
}
if (date[10] == 'y') {
hdtm.tm_mon = 4;
break;
}
return 0;
case 'A':
if (date[10] == 'r') {
hdtm.tm_mon = 3;
break;
}
if (date[10] == 'g') {
hdtm.tm_mon = 7;
break;
}
return 0;
case 'S':
hdtm.tm_mon = 8;
break;
case 'O':
hdtm.tm_mon = 9;
break;
case 'N':
hdtm.tm_mon = 10;
case 'D':
hdtm.tm_mon = 11;
break;
default:
return 0;
}
hdtm.tm_year = uwsgi_str4_num(date+12)-1900;
hdtm.tm_hour = uwsgi_str2_num(date+17);
hdtm.tm_min = uwsgi_str2_num(date+20);
hdtm.tm_sec = uwsgi_str2_num(date+23);
return timegm(&hdtm);
}
#ifdef UWSGI_UDP
ssize_t send_udp_message(uint8_t modifier1, char *host, char *message, uint16_t message_size) {
@@ -346,21 +452,27 @@ int uwsgi_parse_response(struct pollfd *upoll, int timeout, struct uwsgi_header
return 0;
}
// older OSX versions make mess with CMSG_FIRSTHDR
#ifdef __APPLE__
if (!msg.msg_controllen) return 1;
#endif
cmsg = CMSG_FIRSTHDR (&msg);
while(cmsg != NULL) {
if (cmsg->cmsg_len != CMSG_LEN (sizeof (int)) ||
cmsg->cmsg_level != SOL_SOCKET ||
cmsg->cmsg_type != SCM_RIGHTS) continue;
if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) &&
cmsg->cmsg_level == SOL_SOCKET &&
cmsg->cmsg_type && SCM_RIGHTS) {
// upgrade connection to the new socket
#ifdef UWSGI_DEBUG
uwsgi_log("upgrading fd %d to ", upoll->fd);
uwsgi_log("upgrading fd %d to ", upoll->fd);
#endif
close(upoll->fd);
memcpy(&upoll->fd, CMSG_DATA(cmsg), sizeof(int));
close(upoll->fd);
memcpy(&upoll->fd, CMSG_DATA(cmsg), sizeof(int));
#ifdef UWSGI_DEBUG
uwsgi_log("%d\n", upoll->fd);
uwsgi_log("%d\n", upoll->fd);
#endif
}
cmsg = CMSG_NXTHDR (&msg, cmsg);
}
@@ -516,6 +628,18 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->chdir = ptrbuf;
wsgi_req->chdir_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_FILE", 10, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->file = ptrbuf;
wsgi_req->file_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_TOUCH_RELOAD", 18, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->touch_reload = ptrbuf;
wsgi_req->touch_reload_len = strsize;
}
else if (uwsgi.cache_max_items > 0 && !uwsgi_strncmp("UWSGI_CACHE_GET", 15, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->cache_get = ptrbuf;
wsgi_req->cache_get_len = strsize;
}
else if (!uwsgi_strncmp("UWSGI_SETENV", 12, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
char *env_value = memchr(ptrbuf, '=', strsize);
if (env_value) {
@@ -545,6 +669,10 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
wsgi_req->https = ptrbuf;
wsgi_req->https_len = strsize;
}
else if (!uwsgi_strncmp("HTTP_IF_MODIFIED_SINCE", 22, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->if_modified_since = ptrbuf;
wsgi_req->if_modified_since_len = strsize;
}
else if (!uwsgi_strncmp("CONTENT_LENGTH", 14, wsgi_req->hvec[wsgi_req->var_cnt].iov_base, wsgi_req->hvec[wsgi_req->var_cnt].iov_len)) {
wsgi_req->post_cl = get_content_length(ptrbuf, strsize);
}
@@ -570,19 +698,44 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
ptrbuf += strsize;
}
else {
uwsgi_log("Invalid uwsgi request. skip.\n");
return -1;
}
}
else {
uwsgi_log("Invalid uwsgi request. skip.\n");
return -1;
}
}
}
else {
uwsgi_log("Invalid uwsgi request. skip.\n");
return -1;
}
}
// check if data are available in the local cache
if (wsgi_req->cache_get_len > 0) {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_get(wsgi_req->cache_get, wsgi_req->cache_get_len, &cache_value_size);
if (cache_value && cache_value_size > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, cache_value, cache_value_size);
wsgi_req->status = -1;
return -1;
}
}
if (uwsgi.check_cache && wsgi_req->uri_len && wsgi_req->method_len == 3 &&
wsgi_req->method[0] == 'G' && wsgi_req->method[1] == 'E' && wsgi_req->method[2] == 'T') {
uint64_t cache_value_size;
char *cache_value = uwsgi_cache_get(wsgi_req->uri, wsgi_req->uri_len, &cache_value_size);
if (cache_value && cache_value_size > 0) {
wsgi_req->response_size = write(wsgi_req->poll.fd, cache_value, cache_value_size);
wsgi_req->status = -1;
return -1;
}
}
if (uwsgi.manage_script_name) {
if (uwsgi.apps_cnt > 0 && wsgi_req->path_info_len > 1) {
@@ -626,6 +779,7 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
}
}
// check i fa file name uwsgi.check_static+env['PATH_INFO'] exists
if (uwsgi.check_static && wsgi_req->path_info_len > 1) {
struct stat st;
char *filename = uwsgi_concat2n(uwsgi.check_static, uwsgi.check_static_len, wsgi_req->path_info, wsgi_req->path_info_len);
@@ -633,13 +787,27 @@ int uwsgi_parse_vars(struct wsgi_request *wsgi_req) {
uwsgi_log("checking for %s\n", filename);
#endif
if (!stat(filename, &st)) {
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 = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " 304 Not Modified\r\n\r\n", 21);
return -1;
}
}
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", filename);
#endif
// no need to set content-type/content-length, they will be fixed by the http server/router
wsgi_req->sendfile_fd = open(filename, O_RDONLY);
wsgi_req->response_size = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->response_size += write(wsgi_req->poll.fd, " 200 OK\r\n\r\n", 11);
wsgi_req->headers_size = write(wsgi_req->poll.fd, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += write(wsgi_req->poll.fd, " 200 OK\r\n", 9);
set_http_date(st.st_mtime, http_last_modified);
wsgi_req->headers_size += write(wsgi_req->poll.fd, http_last_modified, 48);
wsgi_req->header_cnt = 1;
wsgi_req->response_size += uwsgi_sendfile(wsgi_req);
wsgi_req->status = 200;
free(filename);
+21
View File
@@ -19,6 +19,25 @@ char *uwsgi_queue_get(uint64_t index, uint64_t *size) {
}
void uwsgi_queue_fix() {
uint64_t i;
char *value;
uint64_t size;
for(i=0;i< uwsgi.queue_size;i++) {
// valid record ?
value = uwsgi_queue_get(i, &size);
if (value && size) {
uwsgi.shared->queue_pos++;
}
else {
return;
}
}
}
char *uwsgi_queue_pop(uint64_t *size) {
struct uwsgi_queue_item *uqi;
@@ -70,6 +89,8 @@ int uwsgi_queue_push(char *message, uint64_t size) {
if (size > uwsgi.queue_blocksize + sizeof(struct uwsgi_queue_item))
return 0;
if (!size) return 0;
ptr = ptr + (uwsgi.queue_blocksize*uwsgi.shared->queue_pos);
uqi = (struct uwsgi_queue_item *) ptr;
+21 -8
View File
@@ -8,25 +8,38 @@ from setuptools.dist import Distribution
from setuptools.command.install import install
from setuptools.command.build_ext import build_ext
def patch_bin_path(cmd, conf):
bin_name = conf.get('bin_name')
try:
if not os.path.exists(cmd.install_scripts):
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')))
except:
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
class uWSGIBuilder(build_ext):
def run(self):
conf = uc.uConf('buildconf/default.ini')
bin_name = conf.get('bin_name')
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
conf = uc.uConf('buildconf/default.ini')
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
class uWSGIInstall(install):
def run(self):
# hack, hack and still hack. We need to find a solution for 0.9.6
# hack, hack and still hack. We need to find a solution...
if self.record:
record_file = open(self.record,'w')
conf = uc.uConf('buildconf/default.ini')
bin_name = conf.get('bin_name')
conf.set('bin_name', sys.prefix + '/bin/' + bin_name)
conf = uc.uConf('buildconf/default.ini')
patch_bin_path(self, conf)
uc.build_uwsgi( conf )
class uWSGIDistribution(Distribution):
@@ -38,7 +51,7 @@ class uWSGIDistribution(Distribution):
setup(name='uWSGI',
version='0.9.7-dev',
version='0.9.7.1',
description='The uWSGI server',
author='Unbit',
author_email='info@unbit.it',
-142
View File
@@ -1,142 +0,0 @@
#ifdef UWSGI_STACKLESS
#include "uwsgi.h"
#ifdef UWSGI_STACKLESS
#include <stackless_api.h>
#endif
extern struct uwsgi_server uwsgi;
struct wsgi_request* find_request_by_tasklet(PyTaskletObject *tasklet) {
int i;
for(i=0;i<uwsgi.async;i++) {
if (uwsgi.stackless_table[i]->tasklet == tasklet) {
return uwsgi.stackless_table[i]->wsgi_req;
}
}
return NULL;
}
PyObject *py_uwsgi_stackless_worker(PyObject * self, PyObject * args) {
PyThreadState *ts = PyThreadState_GET();
struct wsgi_request *wsgi_req = find_request_by_tasklet(ts->st.current);
PyObject *zero;
int async_id = wsgi_req->async_id;
//uwsgi_log("i am the tasklet worker\n");
for(;;) {
// wait for request
zero = PyChannel_Receive(uwsgi.workers_channel);
wsgi_req_setup(wsgi_req, async_id);
if (wsgi_req_accept(uwsgi.serverfd, wsgi_req)) {
continue;
}
if (wsgi_req_recv(wsgi_req)) {
continue;
}
uwsgi_close_request(&uwsgi, wsgi_req);
}
}
PyMethodDef uwsgi_stackless_worker[] = { {"uwsgi_stackless_worker", py_uwsgi_stackless_worker, METH_VARARGS, ""} };
void stackless_init(struct uwsgi_server *uwsgi) {
int i;
struct wsgi_request* wsgi_req = uwsgi->wsgi_requests;
PyObject *tasklet_worker = PyCFunction_New(uwsgi_stackless_worker, NULL);
uwsgi->workers_channel = PyChannel_New(NULL);
uwsgi->stackless_table = malloc( sizeof(struct stackless_req*) * uwsgi->async);
if (!uwsgi->stackless_table) {
uwsgi_error("malloc()");
exit(1);
}
for(i=0;i<uwsgi->async;i++) {
uwsgi->stackless_table[i] = malloc(sizeof(struct stackless_req));
if (!uwsgi->stackless_table[i]) {
uwsgi_error("malloc()");
exit(1);
}
memset(uwsgi->stackless_table[i], 0, sizeof(struct stackless_req));
}
uwsgi_log("initializing %d tasklet...", uwsgi->async);
// creating uwsgi->async tasklets
for(i=0;i<uwsgi->async;i++) {
wsgi_req->tasklet = PyTasklet_New(NULL, tasklet_worker);
uwsgi->stackless_table[i]->tasklet = wsgi_req->tasklet;
uwsgi->stackless_table[i]->wsgi_req = wsgi_req;
// useless for now, it will be used for I/O or other messaging
uwsgi->stackless_table[i]->channel = NULL;
wsgi_req->async_id = i;
PyTasklet_Setup(wsgi_req->tasklet, PyTuple_New(0), NULL);
//PyTasklet_Run(wsgi_req->tasklet);
wsgi_req = next_wsgi_req(uwsgi, wsgi_req);
}
uwsgi_log("done\n");
}
void stackless_loop(struct uwsgi_server *uwsgi) {
int i;
PyTaskletObject *int_tasklet;
// tasklets main loop
for(;;) {
//uwsgi->async_running = -1;
//if (PyStackless_GetRunCount() > 0) {
uwsgi->async_running = 0;
//}
uwsgi->async_nevents = async_wait(uwsgi->async_queue, uwsgi->async_events, uwsgi->async, uwsgi->async_running, 0);
if (uwsgi->async_nevents < 0) {
continue;
}
for(i=0; i<uwsgi->async_nevents;i++) {
if (uwsgi->async_events[i].ASYNC_FD == uwsgi->serverfd) {
//pass the connection to the first available tasklet
uwsgi_log("sending new connection...\n");
PyChannel_Send(uwsgi->workers_channel, Py_True);
}
}
/*
if (PyStackless_GetRunCount() > 0) {
PyStackless_Schedule(Py_None, 0);
}
*/
PyStackless_RunWatchdogEx( 10, PY_WATCHDOG_TOTALTIMEOUT);
//int_tasklet = (PyTaskletObject *) PyStackless_RunWatchdog( 1000 );
/*
uwsgi_log("done watchdog %p\n", int_tasklet);
if (!PyTasklet_IsCurrent(int_tasklet)) {
uwsgi_log("re-insert: %d\n", 1);// PyTasklet_Insert(int_tasklet));
}
uwsgi_log("recycle\n");
*/
}
}
#endif
+1
View File
@@ -1,4 +1,5 @@
import sys
import uwsgi
content_type = 'image/png'
filename = 'logo_uWSGI.png'
+58 -1
View File
@@ -70,6 +70,12 @@ void daemonize(char *logfile) {
pid_t pid;
int fdin;
// do not daemonize under emperor
if (uwsgi.has_emperor) {
logto(logfile);
return;
}
pid = fork();
if (pid < 0) {
uwsgi_error("fork()");
@@ -338,6 +344,13 @@ void uwsgi_as_root() {
exit(1);
}
}
if (uwsgi.logfile_chown) {
if (fchown(2, uwsgi.uid, uwsgi.gid)) {
uwsgi_error("fchown()");
exit(1);
}
}
if (uwsgi.gid) {
if (!uwsgi.master_as_root) uwsgi_log("setgid() to %d\n", uwsgi.gid);
if (setgid(uwsgi.gid)) {
@@ -941,6 +954,7 @@ char *uwsgi_strncopy(char *s, int len) {
int uwsgi_get_app_id(char *script_name, int script_name_len, int modifier1) {
int i;
struct stat st;
for(i=0;i<uwsgi.apps_cnt;i++) {
//uwsgi_log("searching for %.*s in %.*s %p\n", script_name_len, script_name, uwsgi.apps[i].mountpoint_len, uwsgi.apps[i].mountpoint, uwsgi.apps[i].callable);
@@ -948,6 +962,15 @@ int uwsgi_get_app_id(char *script_name, int script_name_len, int modifier1) {
continue;
}
if (!uwsgi_strncmp(uwsgi.apps[i].mountpoint, uwsgi.apps[i].mountpoint_len, script_name, script_name_len)) {
if (uwsgi.apps[i].touch_reload) {
if (!stat(uwsgi.apps[i].touch_reload, &st)) {
if (st.st_mtime != uwsgi.apps[i].touch_reload_mtime) {
// serve the new request and reload
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
return -1;
}
}
}
if (modifier1 == -1) return i;
if (modifier1 == uwsgi.apps[i].modifier1) return i;
}
@@ -1349,7 +1372,7 @@ char *uwsgi_open_and_read(char *url, int *size, int add_zero, char *magic_table[
if (add_zero) {
*size = *size + 1;
buffer = realloc(buffer, *size);
buffer[*size] = 0;
buffer[*size-1] = 0;
}
}
@@ -1666,3 +1689,37 @@ int uwsgi_list_has_str(char *list, char *str) {
free(list2);
return 0;
}
int uwsgi_str2_num(char *str) {
int num = 0;
num = 10 * (str[0] - 48);
num += str[1] - 48;
return num;
}
int uwsgi_str3_num(char *str) {
int num = 0;
num = 100 * (str[0] - 48);
num += 10 * (str[1] - 48);
num += str[2] - 48;
return num;
}
int uwsgi_str4_num(char *str) {
int num = 0;
num = 1000 * (str[0] - 48);
num += 100 * (str[1] - 48);
num += 10 * (str[2] - 48);
num += str[3] - 48;
return num;
}
+153 -9
View File
@@ -52,6 +52,8 @@ static struct option long_base_options[] = {
{"cgi-mode", no_argument, 0, 'c'},
{"abstract-socket", no_argument, 0, 'a'},
{"chmod-socket", optional_argument, 0, 'C'},
{"map-socket", required_argument, 0, LONG_ARGS_MAP_SOCKET},
{"chmod", optional_argument, 0, 'C'},
#ifdef UWSGI_THREADING
{"enable-threads", no_argument, 0, 'T'},
#endif
@@ -70,12 +72,15 @@ static struct option long_base_options[] = {
{"cache-store-sync", required_argument, 0, LONG_ARGS_CACHE_STORE_SYNC},
{"queue", required_argument, 0, LONG_ARGS_QUEUE},
{"queue-blocksize", required_argument, 0, LONG_ARGS_QUEUE_BLOCKSIZE},
{"queue-store", required_argument, 0, LONG_ARGS_QUEUE_STORE},
{"queue-store-sync", required_argument, 0, LONG_ARGS_QUEUE_STORE_SYNC},
#ifdef UWSGI_SPOOLER
{"spooler", required_argument, 0, 'Q'},
#endif
{"disable-logging", no_argument, 0, 'L'},
{"pidfile", required_argument, 0, LONG_ARGS_PIDFILE},
{"pidfile2", required_argument, 0, LONG_ARGS_PIDFILE2},
{"chroot", required_argument, 0, LONG_ARGS_CHROOT},
{"gid", required_argument, 0, LONG_ARGS_GID},
{"uid", required_argument, 0, LONG_ARGS_UID},
@@ -125,6 +130,7 @@ static struct option long_base_options[] = {
{"async", required_argument, 0, LONG_ARGS_ASYNC},
#endif
{"logto", required_argument, 0, LONG_ARGS_LOGTO},
{"logfile-chown", no_argument, &uwsgi.logfile_chown, 1},
{"log-syslog", optional_argument, 0, LONG_ARGS_LOG_SYSLOG},
{"log-master", no_argument, 0, LONG_ARGS_LOG_MASTER},
{"logdate", optional_argument, 0, LONG_ARGS_LOG_DATE},
@@ -147,6 +153,7 @@ static struct option long_base_options[] = {
{"routing", no_argument, &uwsgi.routing, 1},
#endif
{"check-static", required_argument, 0, LONG_ARGS_CHECK_STATIC},
{"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},
{"env", required_argument, 0, LONG_ARGS_ENV},
@@ -411,6 +418,13 @@ static void vacuum(void)
uwsgi_log("VACUUM: pidfile removed.\n");
}
}
if (uwsgi.pidfile2) {
if (unlink(uwsgi.pidfile2)) {
uwsgi_error("unlink()");
} else {
uwsgi_log("VACUUM: pidfile2 removed.\n");
}
}
if (uwsgi.chdir) {
if (chdir(uwsgi.chdir)) {
uwsgi_error("chdir()");
@@ -823,9 +837,10 @@ int main(int argc, char *argv[], char *envp[])
if (uwsgi.dump_options) {
struct option *lopt = uwsgi.long_options;
while(lopt->name) {
uwsgi_log("--%s\n", lopt->name);
fprintf(stdout, "%s\n", lopt->name);
lopt++;
}
exit(0);
}
if (uwsgi.show_config) {
@@ -898,7 +913,7 @@ options_parsed:
}
#ifdef UWSGI_DEBUG
uwsgi_log("***\n*** You are running a DEBUG version of uWSGI, plese disable DEBUG in uwsgiconfig.py and recompile it ***\n***\n");
uwsgi_log("***\n*** You are running a DEBUG version of uWSGI, please disable debug in your build profile and recompile it ***\n***\n");
#endif
uwsgi_log("compiled with version: %s on %s\n", __VERSION__, UWSGI_BUILD_DATE);
@@ -941,7 +956,9 @@ options_parsed:
int waitpid_status;
uwsgi_log("*** jailing uWSGI in %s ***\n", uwsgi.ns);
int clone_flags = SIGCHLD|CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|CLONE_NEWNS;
//clone_flags |= CLONE_NEWNET;
if (uwsgi.ns_net) {
clone_flags |= CLONE_NEWNET;
}
pid_t pid = clone(uwsgi_start, stack+PTHREAD_STACK_MIN, clone_flags, (void *)argv);
if (pid == -1) {
uwsgi_error("clone()");
@@ -1089,6 +1106,19 @@ int uwsgi_start(void *v_argv) {
}
}
if (uwsgi.pidfile2 && !uwsgi.is_a_reload) {
uwsgi_log("writing pidfile2 to %s\n", uwsgi.pidfile2);
FILE *pidfile2 = fopen(uwsgi.pidfile2, "w");
if (!pidfile2) {
uwsgi_error_open(uwsgi.pidfile2);
exit(1);
}
if (fprintf(pidfile2, "%d\n", (int) getpid()) < 0) {
uwsgi_log("could not write pidfile2.\n");
}
fclose(pidfile2);
}
if (!uwsgi.no_initial_output) {
if (!uwsgi.master_process) {
uwsgi_log(" *** WARNING: you are running uWSGI without its master process manager ***\n");
@@ -1307,15 +1337,50 @@ int uwsgi_start(void *v_argv) {
exit(1);
}
uwsgi.queue = mmap(NULL, uwsgi.queue_blocksize * uwsgi.queue_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
uwsgi.shared->queue_pos = 0;
uwsgi.shared->queue_pull_pos = 0;
if (uwsgi.queue_store) {
uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size;
int queue_fd;
struct stat qst;
if (stat(uwsgi.queue_store, &qst)) {
uwsgi_log("creating a new queue store file: %s\n", uwsgi.queue_store);
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
if (queue_fd >= 0) {
// fill the queue store
if (ftruncate(queue_fd, uwsgi.queue_filesize)) {
uwsgi_log("ftruncate()");
exit(1);
}
}
}
else {
if ((size_t)qst.st_size != uwsgi.queue_filesize || !S_ISREG(qst.st_mode)) {
uwsgi_log("invalid queue store file. Please remove it or fix queue blocksize/items to match its size\n");
exit(1);
}
queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR );
uwsgi_log("recovered queue from backing store file: %s\n", uwsgi.queue_store);
}
if (queue_fd < 0) {
uwsgi_error_open(uwsgi.queue_store);
exit(1);
}
uwsgi.queue = mmap(NULL, uwsgi.queue_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0);
uwsgi_queue_fix();
}
else {
uwsgi.queue = mmap(NULL, uwsgi.queue_blocksize * uwsgi.queue_size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
}
if (!uwsgi.queue) {
uwsgi_error("mmap()");
exit(1);
}
uwsgi.shared->queue_pos = 0;
uwsgi.shared->queue_pull_pos = 0;
uwsgi.queue_lock = uwsgi_mmap_shared_rwlock();
uwsgi_rwlock_init(uwsgi.queue_lock);
@@ -1638,7 +1703,8 @@ int uwsgi_start(void *v_argv) {
#ifdef UWSGI_THREADING
if (uwsgi.sockets_cnt) {
if (uwsgi.has_threads) {
uwsgi.current_wsgi_req = threaded_current_wsgi_req;
if (uwsgi.threads > 1)
uwsgi.current_wsgi_req = threaded_current_wsgi_req;
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->enable_threads)
uwsgi.p[i]->enable_threads();
@@ -1690,6 +1756,22 @@ int uwsgi_start(void *v_argv) {
}
memset(uwsgi.workers, 0, sizeof(struct uwsgi_worker) * uwsgi.numproc + 1);
for(i=0;i<MAX_SOCKETS;i++) {
if (!uwsgi.map_socket[i]) continue;
char *p = strtok(uwsgi.map_socket[i], ",");
while (p != NULL) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
exit(1);
}
uwsgi.workers[w].sockets_mask[i] = 1;
uwsgi_log("mapped socket %d (%s) to worker %d\n", i, uwsgi.sockets[i].name, w);
p = strtok(NULL, ",");
}
}
uwsgi.mypid = getpid();
masterpid = uwsgi.mypid;
@@ -1894,6 +1976,31 @@ uwsgi.shared->hooks[UWSGI_MODIFIER_PING] = uwsgi_request_ping; //100
//from now on the process is a real worker
}
for(i=0;i<uwsgi.sockets_cnt;i++) {
if (uwsgi.workers[uwsgi.mywid].sockets_mask[i]) {
// disable the socket for this worker
#ifdef UWSGI_DEBUG
uwsgi_log("switching off socket %d (%d) on worker %d\n", i, uwsgi.sockets[i].fd, uwsgi.mywid);
#endif
int fd = uwsgi.sockets[i].fd;
close(fd);
fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != uwsgi.sockets[i].fd) {
if (dup2(fd, uwsgi.sockets[i].fd)) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
uwsgi.sockets_poll[i].fd = -1;
uwsgi.sockets_poll[i].events = 0;
}
}
if (uwsgi.cpu_affinity) {
#ifdef __linux__
cpu_set_t cpuset;
@@ -2219,6 +2326,9 @@ end:
case LONG_ARGS_PIDFILE:
uwsgi.pidfile = optarg;
return 1;
case LONG_ARGS_PIDFILE2:
uwsgi.pidfile2 = optarg;
return 1;
#ifdef UWSGI_UDP
case LONG_ARGS_UDP:
uwsgi.udp_socket = optarg;
@@ -2301,6 +2411,9 @@ end:
case LONG_ARGS_LINUX_NS:
uwsgi.ns = optarg;
return 1;
case LONG_ARGS_LINUX_NS_NET:
uwsgi.ns_net = optarg;
return 1;
#endif
case LONG_ARGS_LIMIT_AS:
uwsgi.rl.rlim_cur = (atoi(optarg)) * 1024 * 1024;
@@ -2334,6 +2447,21 @@ end:
uwsgi.ini = optarg;
return 1;
#endif
case LONG_ARGS_MAP_SOCKET:
p = strchr(optarg, ':');
if (!p) {
uwsgi_log("invalid map-socket syntax, must be socketnum:workerN[,workerN...]\n");
exit(1);
}
p[0] = 0;
int sn = atoi(optarg);
if (sn < 0 || sn >= MAX_SOCKETS) {
uwsgi_log("invalid socket number in map-socket\n");
exit(1);
}
uwsgi.map_socket[sn] = p+1;
p[0] = ':';
return 1;
case LONG_ARGS_CHECK_INTERVAL:
uwsgi.shared->options[UWSGI_OPTION_MASTER_INTERVAL] = atoi(optarg);
return 1;
@@ -2350,6 +2478,13 @@ end:
case LONG_ARGS_CACHE_BLOCKSIZE:
uwsgi.cache_blocksize = atoi(optarg);
return 1;
case LONG_ARGS_QUEUE_STORE:
uwsgi.queue_store = optarg;
uwsgi.master_process = 1;
return 1;
case LONG_ARGS_QUEUE_STORE_SYNC:
uwsgi.queue_store_sync = atoi(optarg);
return 1;
case LONG_ARGS_QUEUE:
uwsgi.queue_size = atoi(optarg);
return 1;
@@ -2995,11 +3130,14 @@ struct uwsgi_help_item main_help[] = {
{"disable-logging", "disable request logging (only errors or server messages will be logged)"},
{"xmlconfig <path>", "path of xml config file"},
{"harakiri <sec>", "set harakiri timeout to <sec> seconds"},
{"harakiri-verbose", "report additional info during harakiri"},
{"processes <n>", "spawn <n> uwsgi worker processes"},
{"workers <n>", "spawn <n> uwsgi worker processes"},
{"max-vars <n>", "set maximum number of vars/headers to <n>"},
{"sharedarea <n>", "create a shared memory area of <n> pages"},
{"cgi-mode", "set cgi mode"},
{"chmod-socket[=NNN]", "chmod socket to 666 or NNN"},
{"chmod[=NNN]", "chmod socket to 666 or NNN"},
{"memory-report", "enable memory usage report"},
{"single-interpreter", "single interpreter mode"},
{"abstract-socket", "set socket in the abstract namespace (Linux only)"},
@@ -3027,7 +3165,7 @@ struct uwsgi_help_item main_help[] = {
{"no-orphans", "automatically kill workers on master's dead"},
{"udp <ip:port>", "bind master process to udp socket on ip:port"},
{"multicast <group>", "set multicast group"},
{"snmp", "enable SNMP support in the UDP server"},
{"snmp[=<addr>]", "enable SNMP support in the UDP server or bind it to <addr>"},
{"snmp-community <value>", "set SNMP community code to <value>"},
{"erlang <name|address>", "enable the Erlang server with node name <name@address>"},
{"erlang-cookie <cookie>", "set the erlang cookie to <cookie>"},
@@ -3037,6 +3175,7 @@ struct uwsgi_help_item main_help[] = {
{"proxy-node <socket>", "add the node <socket> to the proxy"},
{"proxy-max-connections <n>", "set the max number of concurrent connections mnaged by the proxy"},
{"async <n>", "enable async mode with n core"},
{"threads <n>", "spawn <n> threads core"},
{"logto <logfile|addr>", "log to file/udp"},
{"logdate", "add timestamp to loglines"},
{"log-zero", "log requests with 0 response size"},
@@ -3056,6 +3195,7 @@ struct uwsgi_help_item main_help[] = {
{"ugreen-stacksize <n>", "set uGreen stacksize to <n>"},
{"no-site", "do not import site.py on startup"},
{"vhost", "enable virtual hosting"},
{"vhost-host", "use the Host header as the key for virtual hosting"},
{"mount MOUNTPOINT=app", "add a new app under MOUNTPOINT"},
{"routing", "enable uWSGI advanced routing"},
{"http <addr>", "start embedded HTTP server on <addr>"},
@@ -3070,6 +3210,7 @@ struct uwsgi_help_item main_help[] = {
{"cgroup <group>", "run the server in <group> cgroup (Linux only)"},
{"cgroup-opt KEY=VAL", "set cgroup option (Linux only)"},
{"version", "print server version"},
{"attach-daemon <command>", "run <command> under the control of master process"},
{"daemonize <logfile|addr>", "daemonize and log into <logfile> or udp <addr>"},
{ 0, 0 },
@@ -3148,6 +3289,7 @@ void uwsgi_help(void) {
tmp_option = uwsgi_concat2(uhi->key, "");
space = strchr(tmp_option, ' ');
if (!space) space = strstr(tmp_option, "[=");
if (space) space[0] = 0;
if (!strcmp(tmp_option, lopt->name)) {
@@ -3167,6 +3309,7 @@ void uwsgi_help(void) {
if (uhi->key == 0) break;
tmp_option = uwsgi_concat2(uhi->key, "");
space = strchr(tmp_option, ' ');
if (!space) space = strstr(tmp_option, "[=");
if (space) space[0] = 0;
if (!strcmp(tmp_option, lopt->name)) {
@@ -3190,6 +3333,7 @@ void uwsgi_help(void) {
if (uhi->key == 0) break;
tmp_option = uwsgi_concat2(uhi->key, "");
space = strchr(tmp_option, ' ');
if (!space) space = strstr(tmp_option, "[=");
if (space) space[0] = 0;
if (!strcmp(tmp_option, lopt->name)) {
+37 -2
View File
@@ -2,7 +2,7 @@
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs -npsl -di1 */
#define UWSGI_VERSION "0.9.7-dev"
#define UWSGI_VERSION "0.9.7.1"
#define UMAX16 65536
@@ -15,6 +15,7 @@
#define ushared uwsgi.shared
#define MAX_SOCKETS 8
#define MAX_APPS 64
#define MAX_GENERIC_PLUGINS 64
#define MAX_RPC 64
@@ -374,6 +375,10 @@ struct uwsgi_opt {
#define LONG_ARGS_CPU_AFFINITY 17083
#define LONG_ARGS_CACHE_STORE 17084
#define LONG_ARGS_CACHE_STORE_SYNC 17085
#define LONG_ARGS_QUEUE_STORE 17086
#define LONG_ARGS_QUEUE_STORE_SYNC 17087
#define LONG_ARGS_PIDFILE2 17088
#define LONG_ARGS_MAP_SOCKET 17089
#define UWSGI_OK 0
@@ -539,6 +544,9 @@ struct uwsgi_app {
int requests;
char *chdir;
char *touch_reload;
time_t touch_reload_mtime;
};
@@ -641,6 +649,15 @@ struct wsgi_request {
char *chdir;
uint16_t chdir_len;
char *touch_reload;
uint16_t touch_reload_len;
char *cache_get;
uint16_t cache_get_len;
char *if_modified_since;
uint16_t if_modified_since_len;
int fd_closed;
int sendfile_fd;
@@ -785,6 +802,7 @@ struct uwsgi_server {
size_t check_static_len;
char *logfile;
int logfile_chown;
int vhost;
int vhost_host;
@@ -855,6 +873,7 @@ struct uwsgi_server {
int page_size;
char *pidfile;
char *pidfile2;
int harakiri_verbose;
@@ -943,13 +962,16 @@ struct uwsgi_server {
char *cgroup_opt[64];
int cgroup_opt_cnt;
char *ns;
char *ns_net;
#endif
int sockets_cnt;
struct uwsgi_socket sockets[8];
struct uwsgi_socket sockets[MAX_SOCKETS];
// leave a slot for no-orphan mode
struct pollfd sockets_poll[9];
char *map_socket[MAX_SOCKETS];
time_t respawn_delta;
char *mounts[MAX_APPS];
@@ -989,6 +1011,8 @@ struct uwsgi_server {
int cluster_nodes;
int cluster_fd;
struct sockaddr_in mc_cluster_addr;
int check_cache;
uint32_t cache_max_items;
uint64_t *cache_hashtable;
@@ -1003,6 +1027,9 @@ struct uwsgi_server {
uint64_t queue_size;
uint64_t queue_blocksize;
void *queue;
char *queue_store;
size_t queue_filesize;
int queue_store_sync;
void *cache_lock;
void *queue_lock;
@@ -1207,6 +1234,8 @@ struct uwsgi_worker {
uint64_t exceptions;
char sockets_mask[MAX_SOCKETS];
};
char *uwsgi_get_cwd(void);
@@ -1651,3 +1680,9 @@ inline int event_queue_read(void);
inline int event_queue_write(void);
void uwsgi_help(void);
void uwsgi_queue_fix(void);
int uwsgi_str2_num(char *);
int uwsgi_str3_num(char *);
int uwsgi_str4_num(char *);
+3
View File
@@ -234,6 +234,9 @@ class uConf(object):
self.libs.remove('-lpthread')
self.libs.append('-lroot')
if uwsgi_os == 'Darwin':
self.cflags.append('-mmacosx-version-min=10.5')
# set locking subsystem
locking_mode = self.get('locking','auto')