diff --git a/Makefile b/Makefile
index bf75a299..8a1b693e 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ UWSGI_CFLAGS=`python uwsgiconfig.py --cflags`
UWSGI_LDFLAGS=`python uwsgiconfig.py --ldflags`
CFLAGS=$(PYTHON_CFLAGS) $(UWSGI_CFLAGS)
-LD_FLAGS=$(PYTHON_LIBS) $(UWSGI_LDFLAGS)
+LD_FLAGS=$(PYTHON_LIBS) $(UWSGI_LDFLAGS) -export-dynamic
PROGRAM=uwsgi
diff --git a/plugins/example/example_plugin.c b/plugins/example/example_plugin.c
index a83a654b..b8a1ffe7 100644
--- a/plugins/example/example_plugin.c
+++ b/plugins/example/example_plugin.c
@@ -1,20 +1,22 @@
#include "../../uwsgi.h"
-/* gcc `python2.5-config --cflags` -o example_plugin.so -fPIC -shared example_plugin.c */
+/* gcc `python-config --cflags` `python ../../uwsgiconfig.py --cflags` -o example_plugin.so -fPIC -shared example_plugin.c */
int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
fprintf(stderr,"i am the example plugin initialization function with arg: %s\n", args);
return 0;
}
-int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
+int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
char *http = "HTTP/1.1 200 Ok\r\nContent-type: text/html\r\n\r\n
Hello World
" ;
wsgi_req->response_size += write(uwsgi->poll.fd, http, strlen(http));
+ fprintf(stderr,"UWSGI POLL: %p\n", &uwsgi->poll);
+
return 0;
}
-void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
+void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
fprintf(stderr,"i am the example plugin after request function\n");
}
diff --git a/plugins/lua/lua_plugin.c b/plugins/lua/lua_plugin.c
index 2004fe6b..ab13aaf1 100644
--- a/plugins/lua/lua_plugin.c
+++ b/plugins/lua/lua_plugin.c
@@ -85,9 +85,10 @@ int uwsgi_init(struct uwsgi_server *uwsgi, char *args){
}
-int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
+int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
char *ptrbuf;
+ char *buffer = uwsgi->buffer ;
char *bufferend;
uint16_t strsize = 0;
int i;
@@ -197,9 +198,18 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, cha
// send status
if (lua_type(ulua.L, -3) == LUA_TSTRING || lua_type(ulua.L, -3) == LUA_TNUMBER) {
http = lua_tolstring(ulua.L, -3, &slen);
- write(uwsgi->poll.fd, "HTTP/1.1 ", 9);
- write(uwsgi->poll.fd, http, slen);
- write(uwsgi->poll.fd, "\r\n", 2);
+ if (write(uwsgi->poll.fd, "HTTP/1.1 ", 9) != 9) {
+ perror("write()");
+ return -1 ;
+ }
+ if (write(uwsgi->poll.fd, http, slen) != slen) {
+ perror("write()");
+ return -1 ;
+ }
+ if (write(uwsgi->poll.fd, "\r\n", 2) != 2) {
+ perror("write()");
+ return -1 ;
+ }
}
// send headers
@@ -207,15 +217,30 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, cha
lua_pushnil(ulua.L);
while(lua_next(ulua.L, -3) != 0) {
http = lua_tolstring(ulua.L, -2, &slen);
- write(uwsgi->poll.fd, http, slen);
- write(uwsgi->poll.fd, ": ", 2);
+ if (write(uwsgi->poll.fd, http, slen) != slen) {
+ perror("write()");
+ return -1 ;
+ }
+ if (write(uwsgi->poll.fd, ": ", 2) != 2) {
+ perror("write()");
+ return -1 ;
+ }
http = lua_tolstring(ulua.L, -1, &slen);
- write(uwsgi->poll.fd, http, slen);
- write(uwsgi->poll.fd, "\r\n", 2);
+ if (write(uwsgi->poll.fd, http, slen) != slen) {
+ perror("write()");
+ return -1 ;
+ }
+ if (write(uwsgi->poll.fd, "\r\n", 2) != 2) {
+ perror("write()");
+ return -1 ;
+ }
lua_pop(ulua.L, 1);
}
- write(uwsgi->poll.fd, "\r\n", 2);
+ if (write(uwsgi->poll.fd, "\r\n", 2) != 2) {
+ perror("write()");
+ return -1 ;
+ }
// send body with coroutine
lua_pushvalue(ulua.L, -1);
@@ -223,7 +248,10 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, cha
while ( (i = lua_pcall(ulua.L, 0, 1, 0)) == 0) {
if (lua_type(ulua.L, -1) == LUA_TSTRING) {
http = lua_tolstring(ulua.L, -1, &slen);
- write(uwsgi->poll.fd, http, slen);
+ if (write(uwsgi->poll.fd, http, slen) != slen) {
+ perror("write()");
+ return -1 ;
+ }
//fprintf(stderr,"%.*s\n", slen, http);
}
lua_pop(ulua.L, 1);
@@ -236,6 +264,6 @@ int uwsgi_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, cha
}
-void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req, char *buffer) {
+void uwsgi_after_request(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
return;
}
diff --git a/protocol.c b/protocol.c
index f06168c0..211c8a28 100644
--- a/protocol.c
+++ b/protocol.c
@@ -230,6 +230,75 @@ int uwsgi_parse_response(struct pollfd * upoll, int timeout, struct uwsgi_header
return 1;
}
+int uwsgi_parse_vars(struct uwsgi_server *uwsgi, struct wsgi_request *wsgi_req) {
+
+ char *buffer = uwsgi->buffer ;
+
+ char *ptrbuf, *bufferend ;
+
+ uint16_t strsize = 0;
+
+ ptrbuf = buffer;
+ bufferend = ptrbuf + wsgi_req->size;
+
+ /* set an HTTP 500 status as default */
+ wsgi_req->status = 500;
+
+ while (ptrbuf < bufferend) {
+ if (ptrbuf + 2 < bufferend) {
+ memcpy (&strsize, ptrbuf, 2);
+#ifdef __BIG_ENDIAN__
+ strsize = uwsgi_swap16 (strsize);
+#endif
+ ptrbuf += 2;
+ if (ptrbuf + strsize < bufferend) {
+ // var key
+ uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
+ uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
+ ptrbuf += strsize;
+ if (ptrbuf + 2 < bufferend) {
+ memcpy (&strsize, ptrbuf, 2);
+#ifdef __BIG_ENDIAN__
+ strsize = uwsgi_swap16 (strsize);
+#endif
+ ptrbuf += 2;
+ if (ptrbuf + strsize <= bufferend) {
+ if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
+ wsgi_req->var_cnt++;
+ }
+ else {
+ fprintf (stderr, "max vec size reached. skip this header.\n");
+ return -1;
+ }
+ // var value
+ uwsgi->hvec[wsgi_req->var_cnt].iov_base = ptrbuf;
+ uwsgi->hvec[wsgi_req->var_cnt].iov_len = strsize;
+ if (wsgi_req->var_cnt < uwsgi->vec_size - (4 + 1)) {
+ wsgi_req->var_cnt++;
+ }
+ else {
+ fprintf (stderr, "max vec size reached. skip this header.\n");
+ return -1 ;
+ }
+ ptrbuf += strsize;
+ }
+ else {
+ return -1;
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+ }
+ else {
+ return -1;
+ }
+ }
+
+ return 0 ;
+}
+
int uwsgi_ping_node(int node, struct wsgi_request *wsgi_req) {
diff --git a/proxy.c b/proxy.c
index 1de281c5..e7b0d34e 100644
--- a/proxy.c
+++ b/proxy.c
@@ -1,5 +1,17 @@
#ifdef UWSGI_PROXY
+/*
+
+ uWSGI proxy
+
+ it needs one of this tecnology to work:
+
+ - epoll (linux 2.6)
+ - kqueue (various BSD)
+ - /dev/poll Solaris
+
+*/
+
#include "uwsgi.h"
#include
@@ -37,6 +49,10 @@ static void uwsgi_proxy_close(struct uwsgi_proxy_connection *upcs, int fd) {
upcs[upcs[fd].dest_fd].dest_fd = -1 ;
upcs[upcs[fd].dest_fd].status = 0 ;
upcs[upcs[fd].dest_fd].retry = 0 ;
+ if (upcs[upcs[fd].dest_fd].node > -1) {
+ if (uwsgi.shared->nodes[upcs[upcs[fd].dest_fd].node].connections > 0)
+ uwsgi.shared->nodes[upcs[upcs[fd].dest_fd].node].connections--;
+ }
}
if (fd >= 0) {
@@ -44,6 +60,10 @@ static void uwsgi_proxy_close(struct uwsgi_proxy_connection *upcs, int fd) {
upcs[fd].dest_fd = -1 ;
upcs[fd].status = 0 ;
upcs[fd].retry = 0 ;
+ if (upcs[fd].node > -1) {
+ if (uwsgi.shared->nodes[upcs[fd].node].connections > 0)
+ uwsgi.shared->nodes[upcs[fd].node].connections--;
+ }
}
}
@@ -59,11 +79,24 @@ static int uwsgi_proxy_find_next_node(int current_node) {
// is it a good node ?
if (uwsgi.shared->nodes[current_node].name[0] != 0 && uwsgi.shared->nodes[current_node].status == UWSGI_NODE_OK) {
- return current_node ;
+ if (uwsgi.shared->nodes[current_node].connections < uwsgi.shared->nodes[current_node].workers)
+ return current_node ;
}
// try to find a better one
+ for(i=0;inodes[i].name[0] != 0 && uwsgi.shared->nodes[i].status == UWSGI_NODE_OK) {
+ if (uwsgi.shared->nodes[i].connections < uwsgi.shared->nodes[i].workers)
+ return i ;
+ }
+ }
+
+ // ok, it is a very loaded system, fallback to round robin
+ if (uwsgi.shared->nodes[current_node].name[0] != 0 && uwsgi.shared->nodes[current_node].status == UWSGI_NODE_OK) {
+ return current_node ;
+ }
+
for(i=0;inodes[i].name[0] != 0 && uwsgi.shared->nodes[i].status == UWSGI_NODE_OK) {
return i ;
@@ -162,6 +195,7 @@ void uwsgi_proxy(int proxyfd) {
perror("accept()");
continue;
}
+ upcs[ee.data.fd].node = -1;
// now connect to the first worker available
@@ -171,6 +205,7 @@ void uwsgi_proxy(int proxyfd) {
uwsgi_proxy_close(upcs, ee.data.fd);
continue;
}
+ upcs[upcs[ee.data.fd].dest_fd].node = -1;
// set nonblocking
if (ioctl(upcs[ee.data.fd].dest_fd, FIONBIO, &nonblocking)) {
@@ -189,6 +224,7 @@ void uwsgi_proxy(int proxyfd) {
}
upcs[upcs[ee.data.fd].dest_fd].node = next_node ;
rc = connect(upcs[ee.data.fd].dest_fd, (struct sockaddr *) &uwsgi.shared->nodes[next_node].ucn_addr, sizeof(struct sockaddr_in));
+ uwsgi.shared->nodes[next_node].connections++;
if (!rc) {
// connected to worker, put it in the epoll_list
diff --git a/uwsgi.c b/uwsgi.c
index 02f46108..564b9405 100644
--- a/uwsgi.c
+++ b/uwsgi.c
@@ -130,20 +130,23 @@ void reap_them_all () {
void harakiri () {
PyThreadState *_myself;
-#ifndef ROCK_SOLID
+
+/* CHECK ROCK_SOLID
struct uwsgi_app *wi = NULL;
if (wsgi_req.app_id >= 0) {
wi = &uwsgi.wsgi_apps[wsgi_req.app_id];
}
-#endif
+ end rock_solid */
+
PyGILState_Ensure ();
_myself = PyThreadState_Get ();
if (wi) {
+/*
#ifdef ROCK_SOLID
fprintf (stderr, "\nF*CK !!! i must kill myself (pid: %d) wi: %p wi->wsgi_harakiri: %p thread_state: %p frame: %p...\n", uwsgi.mypid, wi, wi->wsgi_harakiri, _myself, _myself->frame);
#else
+*/
fprintf (stderr, "\nF*CK !!! i must kill myself (pid: %d app_id: %d) wi: %p wi->wsgi_harakiri: %p thread_state: %p frame: %p...\n", uwsgi.mypid, wsgi_req.app_id, wi, wi->wsgi_harakiri, _myself, _myself->frame);
-#endif
if (wi->wsgi_harakiri) {
PyEval_CallObject (wi->wsgi_harakiri, wi->wsgi_args);
@@ -196,7 +199,8 @@ PyObject *py_uwsgi_write (PyObject * self, PyObject * args) {
if (PyString_Check (data)) {
content = PyString_AsString (data);
len = PyString_Size (data);
-#ifndef ROCK_SOLID
+
+#ifdef UWSGI_THREADING
if (uwsgi.has_threads && uwsgi.shared->options[UWSGI_OPTION_THREADS] == 1) {
Py_BEGIN_ALLOW_THREADS wsgi_req.response_size = write (uwsgi.poll.fd, content, len);
Py_END_ALLOW_THREADS}
@@ -212,7 +216,7 @@ PyObject *py_uwsgi_write (PyObject * self, PyObject * args) {
}
}
#endif
-#ifndef ROCK_SOLID
+#ifdef UWSGI_THREADING
}
#endif
}
@@ -234,12 +238,9 @@ PyObject *py_uwsgi_spit (PyObject * self, PyObject * args) {
PyObject *headers, *head;
PyObject *h_key, *h_value;
int i, j;
+
#ifndef UNBIT
-#ifdef ROCK_SOLID
- int base = 4;
-#else
int base = 0;
-#endif
#else
int base = 4;
#endif
@@ -464,11 +465,9 @@ int main (int argc, char *argv[], char *envp[]) {
uint64_t master_cycles = 0 ;
struct timeval check_interval = {.tv_sec = 1,.tv_usec = 0 };
-#ifndef PYTHREE
-#ifndef ROCK_SOLID
+#ifdef UWSGI_EMBEDDED
PyObject *uwsgi_module;
-#endif
#endif
char *pyargv[MAX_PYARGV];
int pyargc = 1;
@@ -654,6 +653,8 @@ int main (int argc, char *argv[], char *envp[]) {
}
}
+ uwsgi.binary_path = argv[0] ;
+
#ifndef UNBIT
while ((i = getopt_long (argc, argv, "s:p:t:x:d:l:O:v:b:mcaCTPiMhrR:z:w:j:H:A:Q:L", long_options, &option_index)) != -1) {
#else
@@ -669,7 +670,7 @@ int main (int argc, char *argv[], char *envp[]) {
}
#endif
- if (uwsgi.binary_path == NULL) {
+ if (uwsgi.binary_path == argv[0]) {
cwd = uwsgi_get_cwd ();
uwsgi.binary_path = malloc (strlen (argv[0]) + 1);
if (uwsgi.binary_path == NULL) {
@@ -680,9 +681,7 @@ int main (int argc, char *argv[], char *envp[]) {
}
#ifndef UNBIT
-#ifndef ROCK_SOLID
if (uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] == 0) {
-#endif
#endif
if (uwsgi.test_module == NULL) {
fprintf (stderr, "*** Starting uWSGI (%dbit) on [%.*s] ***\n", (int) (sizeof (void *)) * 8, 24, ctime ((const time_t *) &uwsgi.start_tv.tv_sec));
@@ -848,8 +847,7 @@ int main (int argc, char *argv[], char *envp[]) {
wsgi_spitout = PyCFunction_New (uwsgi_spit_method, NULL);
wsgi_writeout = PyCFunction_New (uwsgi_write_method, NULL);
-#ifndef PYTHREE
-#ifndef ROCK_SOLID
+#ifdef UWSGI_EMBEDDED
uwsgi_module = Py_InitModule ("uwsgi", null_methods);
if (uwsgi_module == NULL) {
fprintf (stderr, "could not initialize the uwsgi python module\n");
@@ -898,7 +896,6 @@ int main (int argc, char *argv[], char *envp[]) {
init_uwsgi_embedded_module ();
#endif
-#endif
@@ -1198,13 +1195,11 @@ int main (int argc, char *argv[], char *envp[]) {
#ifndef UNBIT
-#ifndef ROCK_SOLID
if (no_server) {
fprintf (stderr, "no-server mode requested. Goodbye.\n");
exit (0);
}
#endif
-#endif
// is this a proxy only worker ?
@@ -1678,6 +1673,7 @@ int main (int argc, char *argv[], char *envp[]) {
}
else {
#endif
+ fprintf(stderr,"POLL ADDR: %p\n", &uwsgi.poll);
if (!uwsgi_parse_response (&uwsgi.poll, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT], (struct uwsgi_header *) &wsgi_req, uwsgi.buffer)) {
continue;
}
@@ -1791,7 +1787,6 @@ void init_uwsgi_vars () {
}
-#ifndef ROCK_SOLID
int init_uwsgi_app (PyObject * force_wsgi_dict, PyObject * my_callable) {
PyObject *wsgi_module, *wsgi_dict = NULL;
PyObject *pymain, *zero;
@@ -2310,7 +2305,6 @@ void uwsgi_wsgi_config () {
}
-#endif
#ifdef UNBIT
int uri_to_hex () {
@@ -2511,7 +2505,6 @@ pid_t spooler_start (int serverfd, PyObject * uwsgi_module) {
void manage_opt(int i, char *optarg) {
switch (i) {
-#ifndef ROCK_SOLID
#ifndef UNBIT
case LONG_ARGS_PIDFILE:
uwsgi.pidfile = optarg;
@@ -2565,7 +2558,6 @@ void manage_opt(int i, char *optarg) {
uwsgi.rl.rlim_cur = (atoi (optarg)) * 1024 * 1024;
uwsgi.rl.rlim_max = uwsgi.rl.rlim_cur;
break;
-#endif
case LONG_ARGS_PASTE:
uwsgi.single_interpreter = 1;
uwsgi.paste = optarg;
@@ -2650,7 +2642,6 @@ void manage_opt(int i, char *optarg) {
case 'r':
uwsgi.shared->options[UWSGI_OPTION_REAPER] = 1;
break;
-#ifndef ROCK_SOLID
case 'w':
uwsgi.single_interpreter = 1;
uwsgi.wsgi_config = optarg;
@@ -2661,7 +2652,6 @@ void manage_opt(int i, char *optarg) {
case 'O':
uwsgi.py_optimize = atoi (optarg);
break;
-#endif
case 't':
uwsgi.shared->options[UWSGI_OPTION_HARAKIRI] = atoi (optarg);
break;
@@ -2669,11 +2659,9 @@ void manage_opt(int i, char *optarg) {
uwsgi.buffer_size = atoi (optarg);
break;
#ifndef UNBIT
-#ifndef ROCK_SOLID
case 'c':
uwsgi.shared->options[UWSGI_OPTION_CGI_MODE] = 1;
break;
-#endif
case 'a':
uwsgi.abstract_socket = 1;
break;
@@ -2692,7 +2680,6 @@ void manage_opt(int i, char *optarg) {
uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT] = atoi (optarg);
}
break;
-#ifndef ROCK_SOLID
case 'T':
uwsgi.has_threads = 1;
uwsgi.shared->options[UWSGI_OPTION_THREADS] = 1;
@@ -2703,7 +2690,6 @@ void manage_opt(int i, char *optarg) {
case 'i':
uwsgi.single_interpreter = 1;
break;
-#endif
#ifndef UNBIT
case 'h':
fprintf (stdout, "Usage: %s [options...]\n\
@@ -2746,6 +2732,14 @@ void manage_opt(int i, char *optarg) {
\t--pyargv \t\t\tassign args to python sys.argv\n\
\t--limit-as \t\t\tlimit the address space of processes to MB megabytes\n\
\t--udp \t\t\tbind master process to udp socket on ip:port\n\
+\t--erlang \t\tenable the Erlang server with node name \n\
+\t--erlang-cookie \ttset the erlang cookie to \n\
+\t--nagios\t\t\tdo a nagios check\n\
+\t--binary-path \ttset the path for the next reload of uWSGI (needed for chroot environments)\n\
+\t--proxy \t\trun the uwsgi proxy on socket \n\
+\t--proxy-node \t\tadd the node to the proxy\n\
+\t--proxy-max-connections \tset the max number of concurrent connections mnaged by the proxy\n\
+\t--wsgi-file \t\tload the wsgi file\n\
\t-d|--daemonize \tdaemonize and log into \n", uwsgi.binary_path);
exit (1);
case 0:
diff --git a/uwsgi.h b/uwsgi.h
index b7eff705..20de96b1 100644
--- a/uwsgi.h
+++ b/uwsgi.h
@@ -394,6 +394,7 @@ struct uwsgi_cluster_node {
struct sockaddr_in ucn_addr;
int workers ;
+ int connections ;
int status ;
time_t last_seen;
@@ -528,6 +529,7 @@ struct uwsgi_cluster_node {
PyObject *uwsgi_send_message (const char *, int, uint8_t, uint8_t, char *, int, int);
int uwsgi_parse_response (struct pollfd *, int, struct uwsgi_header *, char *);
+ int uwsgi_parse_vars (struct uwsgi_server *, struct wsgi_request *);
int uwsgi_enqueue_message (char *, int, uint8_t, uint8_t, char *, int, int);
diff --git a/uwsgi_pymodule.c b/uwsgi_pymodule.c
index bcbf910e..72f8a7be 100644
--- a/uwsgi_pymodule.c
+++ b/uwsgi_pymodule.c
@@ -541,7 +541,7 @@ PyObject *py_uwsgi_load_plugin(PyObject *self, PyObject *args) {
return NULL ;
}
- plugin_handle = dlopen(plugin_name, RTLD_LAZY);
+ plugin_handle = dlopen(plugin_name, RTLD_NOW|RTLD_GLOBAL);
if (!plugin_handle) {
fprintf (stderr, "%s\n", dlerror());
}