mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-10-04 16:08:31 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6692276472 | ||
|
|
81c09a9c9c | ||
|
|
6a0a367ec3 | ||
|
|
bdf533d62b | ||
|
|
1aba0bc26c | ||
|
|
aac6e9a365 | ||
|
|
9da732d96c | ||
|
|
328ba43ed2 | ||
|
|
62d3253b02 | ||
|
|
e5ba01e707 | ||
|
|
82c25f7f8c | ||
|
|
8791866ea0 | ||
|
|
8f10b8fece | ||
|
|
0d28d210d4 | ||
|
|
2368a5a050 | ||
|
|
74a9b1b41d | ||
|
|
672c49e8eb | ||
|
|
225db32636 | ||
|
|
01541e4a50 | ||
|
|
357e260b45 | ||
|
|
a2513b1851 | ||
|
|
bbe8604054 | ||
|
|
58a33de7f7 | ||
|
|
ab7abc6a48 | ||
|
|
4986bdf202 | ||
|
|
11aaddac98 | ||
|
|
da9b2b4378 | ||
|
|
9771a98bc6 | ||
|
|
033ee5f4e9 | ||
|
|
1383163627 | ||
|
|
1d31b35c4f | ||
|
|
7b2cc757b2 | ||
|
|
68cddd1c2e | ||
|
|
b2a9fbbc5c | ||
|
|
0fcb13b9f1 | ||
|
|
938a22ce2e | ||
|
|
2df5dbfe52 | ||
|
|
feed0d0faa | ||
|
|
c8373d20a9 | ||
|
|
170267a04a | ||
|
|
bd5969db67 | ||
|
|
02256c013c | ||
|
|
89be9a0d4a |
@@ -49,3 +49,5 @@ af490b8c30f83bc5fb6f3837a760981474647755 1.0-rc10
|
||||
ede5c664978bb40e476e8d4a5789562928f28507 1.1-rc3
|
||||
ef99144291f06822d026e981d5d856cbec14d867 1.1-rc4
|
||||
e1568fd16b7b586cc72deb4dfccbbe64ae0b84df 1.1
|
||||
24c8fe5a26e557db41cf1cee45b8964d5885e484 1.2-rc1
|
||||
29de0fb320bc0a1ce84972f9f249360e315d3c10 1.2-rc2
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
*** april 2012 ***
|
||||
|
||||
* 1.2 [20120430]
|
||||
|
||||
- PyPy support
|
||||
- Improved gevent support with threads
|
||||
- Python auto-reload subsystem
|
||||
- added --spooler-max-tasks
|
||||
- pthread robust mutexes support in Linux and Solaris
|
||||
- posix semaphores support in FreeBSD9
|
||||
- thread-safe ctime() reporting
|
||||
- interval support in cron subsystem
|
||||
- improved syslog support
|
||||
- better management of disconnected clients
|
||||
- static files serving improvements
|
||||
- another set of multithreading optimizations
|
||||
- minor fixes in the Rack plugin
|
||||
- Upstart socket-activation support
|
||||
|
||||
|
||||
*** march 2012 ***
|
||||
|
||||
* 1.1 [20120317]
|
||||
|
||||
@@ -186,7 +186,7 @@ static void log_debug(const char *file, int line, int ami, request_rec *r, const
|
||||
ap_log_rerror(file, line, APLOG_MODULE_INDEX, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
#else
|
||||
static void log_debug(const char *file, int line, request_rec *r, const
|
||||
char *msg)
|
||||
char *msg) {
|
||||
ap_log_rerror(file, line, APLOG_DEBUG, APR_SUCCESS, r, "uwsgi: %s", msg);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ void cluster_setup() {
|
||||
// receive the packet
|
||||
char clusterbuf[4096];
|
||||
if (!uwsgi_hooked_parse_dict_dgram(uwsgi.cluster_fd, clusterbuf, 4096, 99, 1, cluster_manage_opt, NULL)) {
|
||||
uwsgi_configure(-1);
|
||||
uwsgi_configure();
|
||||
goto options_parsed;
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -421,7 +421,8 @@ int event_queue_interesting_fd(void *events, int id) {
|
||||
int event_queue_interesting_fd_has_error(void *events, int id) {
|
||||
struct kevent *ev = (struct kevent *) events;
|
||||
|
||||
if ( ( (ev[id].flags == EV_ERROR) || (ev[id].flags == EV_EOF) || (ev[id].flags == (EV_EOF|EV_ERROR))) ) {
|
||||
// DO NOT CHECK FOR EOF !!!
|
||||
if ( ev[id].flags & EV_ERROR ) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
+1
-1
@@ -14,7 +14,7 @@ def application(env, start_response):
|
||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||
yield "foobar<br/>"
|
||||
if uwsgi.loop == 'gevent':
|
||||
gevent.sleep(10)
|
||||
gevent.sleep(3)
|
||||
yield str(env['wsgi.input'].fileno())
|
||||
yield "<h1>Hello World</h1>"
|
||||
try:
|
||||
|
||||
@@ -481,7 +481,7 @@ void uwsgi_setup_locking() {
|
||||
// use the fastest avaikable locking
|
||||
if (uwsgi.lock_engine) {
|
||||
if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
|
||||
uwsgi_log("lock engine: ipcsem\n");
|
||||
uwsgi_log_initial("lock engine: ipcsem\n");
|
||||
atexit(uwsgi_ipcsem_clear);
|
||||
uwsgi.lock_ops.lock_init = uwsgi_lock_ipcsem_init;
|
||||
uwsgi.lock_ops.lock_check = uwsgi_lock_ipcsem_check;
|
||||
@@ -498,7 +498,7 @@ void uwsgi_setup_locking() {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_log("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
|
||||
uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
|
||||
#ifdef UWSGI_IPCSEM_ATEXIT
|
||||
atexit(uwsgi_ipcsem_clear);
|
||||
#endif
|
||||
|
||||
@@ -136,6 +136,7 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
char *msg1 = " via sendfile() ";
|
||||
#endif
|
||||
char *msg3 = " via route() ";
|
||||
char *msg4 = " via offload() ";
|
||||
|
||||
struct uwsgi_app *wi;
|
||||
|
||||
@@ -159,6 +160,9 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->status == -17) {
|
||||
via = msg3;
|
||||
}
|
||||
else if (wsgi_req->status == -30) {
|
||||
via = msg4;
|
||||
}
|
||||
|
||||
#ifdef __sun__
|
||||
ctime_r((const time_t *) &wsgi_req->start_of_request.tv_sec, time_request, 26);
|
||||
|
||||
@@ -120,7 +120,6 @@ void *zeromq_loop(void *arg1) {
|
||||
struct wsgi_request *wsgi_req = uwsgi.wsgi_requests[core_id];
|
||||
uwsgi.zeromq_recv_flag = 0;
|
||||
zmq_pollitem_t zmq_poll_items[3];
|
||||
char uwsgi_signal;
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
|
||||
@@ -188,38 +187,12 @@ void *zeromq_loop(void *arg1) {
|
||||
}
|
||||
|
||||
if (zmq_poll_items[1].revents & ZMQ_POLLIN) {
|
||||
if (read(uwsgi.signal_socket, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(uwsgi.signal_socket, "worker", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (zmq_poll_items[2].revents & ZMQ_POLLIN) {
|
||||
if (read(uwsgi.my_signal_socket, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(uwsgi.my_signal_socket, "worker", uwsgi.mywid);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -1601,7 +1601,12 @@ nextlock:
|
||||
// noop
|
||||
}
|
||||
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
if (WIFSIGNALED(waitpid_status)) {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
|
||||
|
||||
@@ -772,6 +772,7 @@ void uwsgi_send_stats(int fd) {
|
||||
stats_send_llu("\"delta_requests\": %llu, ", uwsgi.workers[i + 1].delta_requests);
|
||||
stats_send_llu("\"exceptions\": %llu, ", uwsgi.workers[i + 1].exceptions);
|
||||
stats_send_llu("\"signals\": %llu, ", uwsgi.workers[i + 1].signals);
|
||||
stats_send_llu("\"static_offload_threads\": %llu, ", uwsgi.workers[i + 1].static_offload_threads);
|
||||
|
||||
if (uwsgi.workers[i + 1].cheaped) {
|
||||
fprintf(output, "\"status\": \"cheap\", ");
|
||||
|
||||
@@ -7,6 +7,7 @@ struct uwsgi_carbon {
|
||||
int freq;
|
||||
int timeout;
|
||||
char *id;
|
||||
int no_workers;
|
||||
} u_carbon;
|
||||
|
||||
struct uwsgi_option carbon_options[] = {
|
||||
@@ -14,6 +15,7 @@ struct uwsgi_option carbon_options[] = {
|
||||
{"carbon-timeout", required_argument, 0, "set carbon connection timeout", uwsgi_opt_set_int, &u_carbon.timeout, 0},
|
||||
{"carbon-freq", required_argument, 0, "set carbon push frequency", uwsgi_opt_set_int, &u_carbon.freq, 0},
|
||||
{"carbon-id", required_argument, 0, "set carbon id", uwsgi_opt_set_str, &u_carbon.id, 0},
|
||||
{"carbon-no-workers", no_argument, 0, "disable generation of single worker metrics", uwsgi_opt_true, &u_carbon.no_workers, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -73,6 +75,8 @@ void carbon_master_cycle() {
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) uwsgi.workers[0].requests, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
if (u_carbon.no_workers) goto gmetrics;
|
||||
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.worker%d.requests %llu %llu\n", uwsgi.hostname, u_carbon.id, i, (unsigned long long ) uwsgi.workers[i].requests, (unsigned long long ) uwsgi.current_time);
|
||||
@@ -109,6 +113,8 @@ void carbon_master_cycle() {
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
}
|
||||
|
||||
gmetrics:
|
||||
|
||||
rlen = snprintf(ptr, 4096, "uwsgi.%s.%s.rss_size %llu %llu\n", uwsgi.hostname, u_carbon.id, (unsigned long long ) total_rss, (unsigned long long ) uwsgi.current_time);
|
||||
if (rlen < 1) goto clear;
|
||||
if (write(fd, ptr, rlen) <= 0) { uwsgi_error("write()"); goto clear;}
|
||||
|
||||
@@ -512,7 +512,8 @@ int uwsgi_cgi_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
else {
|
||||
docroot = uwsgi_cgi_get_docroot(wsgi_req->path_info, wsgi_req->path_info_len, &need_free, &is_a_file, &discard_base, &script_name);
|
||||
docroot_len = strlen(docroot);
|
||||
if (docroot)
|
||||
docroot_len = strlen(docroot);
|
||||
}
|
||||
|
||||
if (docroot == NULL || docroot_len == 0) {
|
||||
|
||||
@@ -582,6 +582,10 @@ void fastrouter_loop(int id) {
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef __linux__
|
||||
uwsgi_socket_b(new_connection);
|
||||
#endif
|
||||
|
||||
ufr.fr_table[new_connection] = alloc_fr_session();
|
||||
ufr.fr_table[new_connection]->fd = new_connection;
|
||||
ufr.fr_table[new_connection]->instance_fd = -1;
|
||||
|
||||
+15
-18
@@ -34,34 +34,20 @@ struct wsgi_request *uwsgi_gevent_current_wsgi_req(void) {
|
||||
|
||||
PyObject *py_uwsgi_gevent_signal_handler(PyObject * self, PyObject * args) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
int signal_socket;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "i:uwsgi_gevent_signal_handler", &signal_socket)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (read(signal_socket, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
// close the socket to end the mess...from now on the worker is alone (no master)
|
||||
else close(signal_socket);
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(signal_socket, "worker", uwsgi.mywid);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// the following twi functions are called whenever an event is available in the signal queue
|
||||
// they both trigger the same function
|
||||
PyObject *py_uwsgi_gevent_signal(PyObject * self, PyObject * args) {
|
||||
|
||||
PyTuple_SetItem(ugevent.signal_args, 1, PyInt_FromLong(uwsgi.signal_socket));
|
||||
@@ -180,7 +166,6 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
goto clear_and_stop;
|
||||
}
|
||||
else if (ret == watcher) {
|
||||
|
||||
status = wsgi_req->socket->proto(wsgi_req);
|
||||
if (status < 0) {
|
||||
goto clear_and_stop;
|
||||
@@ -203,6 +188,7 @@ PyObject *py_uwsgi_gevent_request(PyObject * self, PyObject * args) {
|
||||
if (wsgi_req->async_status <= UWSGI_OK) {
|
||||
goto clear;
|
||||
}
|
||||
wsgi_req->switches++;
|
||||
// switch after each yield
|
||||
GEVENT_SWITCH;
|
||||
}
|
||||
@@ -239,6 +225,17 @@ PyMethodDef uwsgi_gevent_signal_handler_def[] = { {"uwsgi_gevent_signal_handler"
|
||||
|
||||
void gevent_loop() {
|
||||
|
||||
if (!uwsgi.has_threads && uwsgi.mywid == 1) {
|
||||
uwsgi_log("!!! Running gevent without threads IS NOT recommended, enable them with --enable-threads !!!\n");
|
||||
}
|
||||
|
||||
// get the GIL
|
||||
UWSGI_GET_GIL
|
||||
|
||||
// ..then reset GIL subsystem as noop (gevent IO will take care of it...)
|
||||
up.gil_get = gil_fake_get;
|
||||
up.gil_release = gil_fake_release;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
if (uwsgi.async < 2) {
|
||||
|
||||
+6
-5
@@ -592,6 +592,9 @@ void http_loop(int id) {
|
||||
taken = 1;
|
||||
break;
|
||||
}
|
||||
#ifndef __linux__
|
||||
uwsgi_socket_b(new_connection);
|
||||
#endif
|
||||
|
||||
uhttp_table[new_connection] = alloc_uhttp_session();
|
||||
uhttp_table[new_connection]->fd = new_connection;
|
||||
@@ -892,10 +895,9 @@ void http_loop(int id) {
|
||||
break;
|
||||
}
|
||||
|
||||
len = send(uhttp_session->fd, bbuf, len, 0);
|
||||
|
||||
if (len <= 0) {
|
||||
if (len < 0)
|
||||
ssize_t s_len = send(uhttp_session->fd, bbuf, len, 0);
|
||||
if (s_len <= 0) {
|
||||
if (s_len < 0)
|
||||
uwsgi_error("send()");
|
||||
close(uhttp_session->fd);
|
||||
close(uhttp_session->instance_fd);
|
||||
@@ -910,7 +912,6 @@ void http_loop(int id) {
|
||||
// body from client
|
||||
else if (interesting_fd == uhttp_session->fd) {
|
||||
|
||||
//uwsgi_log("receiving body...\n");
|
||||
len = recv(uhttp_session->fd, bbuf, UMAX16, 0);
|
||||
#ifdef UWSGI_EVENT_USE_PORT
|
||||
event_queue_add_fd_read(uhttp_queue, uhttp_session->fd);
|
||||
|
||||
@@ -150,7 +150,12 @@ int uwsgi_python_init() {
|
||||
|
||||
#ifndef UWSGI_PYPY
|
||||
char *pyversion = strchr(Py_GetVersion(), '\n');
|
||||
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
|
||||
if (!pyversion) {
|
||||
uwsgi_log_initial("Python version: %s\n", Py_GetVersion());
|
||||
}
|
||||
else {
|
||||
uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
|
||||
}
|
||||
#else
|
||||
uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
|
||||
#endif
|
||||
@@ -189,6 +194,10 @@ int uwsgi_python_init() {
|
||||
|
||||
Py_Initialize();
|
||||
|
||||
if (!uwsgi.has_threads) {
|
||||
uwsgi_log("*** Python threads support is disabled. You can enable it with --enable-threads ***\n");
|
||||
}
|
||||
|
||||
up.wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL);
|
||||
up.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL);
|
||||
|
||||
@@ -275,7 +284,7 @@ void uwsgi_python_atexit() {
|
||||
PyObject *module = PyImport_ImportModule("atexit");
|
||||
Py_XDECREF(module);
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
if (uwsgi.has_threads) {
|
||||
if (!PyImport_AddModule("dummy_threading"))
|
||||
PyErr_Clear();
|
||||
}
|
||||
@@ -1187,22 +1196,15 @@ void uwsgi_python_init_thread(int core_id) {
|
||||
}
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
int uwsgi_check_python_mtime(PyObject *times_dict, uint64_t cycles, char *filename) {
|
||||
int uwsgi_check_python_mtime(PyObject *times_dict, char *filename) {
|
||||
struct stat st;
|
||||
|
||||
PyObject *py_mtime = PyDict_GetItemString(times_dict, filename);
|
||||
if (!py_mtime) {
|
||||
if (cycles == 0) {
|
||||
if (stat(filename, &st)) {
|
||||
return 0;
|
||||
}
|
||||
PyDict_SetItemString(times_dict, filename, PyLong_FromLong(st.st_mtime));
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[uwsgi-python-reloader] found new module/file: %s\n", filename);
|
||||
kill(uwsgi.workers[0].pid, SIGHUP);
|
||||
return 1;
|
||||
if (stat(filename, &st)) {
|
||||
return 0;
|
||||
}
|
||||
PyDict_SetItemString(times_dict, filename, PyLong_FromLong(st.st_mtime));
|
||||
}
|
||||
// the record is already tracked;
|
||||
else {
|
||||
@@ -1268,7 +1270,6 @@ cycle:
|
||||
}
|
||||
PyObject *times_dict = PyDict_New();
|
||||
char *filename;
|
||||
uint64_t cycles = 0;
|
||||
for(;;) {
|
||||
UWSGI_RELEASE_GIL;
|
||||
sleep(up.auto_reload);
|
||||
@@ -1314,7 +1315,7 @@ cycle:
|
||||
else {
|
||||
filename = uwsgi_concat2(mod_filename, "");
|
||||
}
|
||||
if (uwsgi_check_python_mtime(times_dict, cycles, filename)) {
|
||||
if (uwsgi_check_python_mtime(times_dict, filename)) {
|
||||
UWSGI_RELEASE_GIL;
|
||||
return NULL;
|
||||
}
|
||||
@@ -1323,7 +1324,6 @@ cycle:
|
||||
Py_DECREF(zero);
|
||||
#endif
|
||||
}
|
||||
cycles++;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
||||
@@ -1025,6 +1025,17 @@ PyObject *py_uwsgi_setprocname(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_ready(PyObject * self, PyObject * args) {
|
||||
|
||||
if (ushared->ready) {
|
||||
Py_INCREF(Py_True);
|
||||
return Py_True;
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_in_farm(PyObject * self, PyObject * args) {
|
||||
|
||||
char *farm_name = NULL;
|
||||
@@ -3103,6 +3114,8 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"mule_get_msg", (PyCFunction) py_uwsgi_mule_get_msg, METH_VARARGS|METH_KEYWORDS, ""},
|
||||
{"farm_get_msg", py_uwsgi_farm_get_msg, METH_VARARGS, ""},
|
||||
{"in_farm", py_uwsgi_in_farm, METH_VARARGS, ""},
|
||||
|
||||
{"ready", py_uwsgi_ready, METH_VARARGS, ""},
|
||||
//{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""},
|
||||
|
||||
{NULL, NULL},
|
||||
|
||||
@@ -325,6 +325,11 @@ void uwsgi_ruby_gemset(char *gemset) {
|
||||
|
||||
}
|
||||
|
||||
static void rack_hack_dollar_zero(VALUE name, ID id) {
|
||||
ur.dollar_zero = rb_obj_as_string(name);
|
||||
rb_obj_taint(ur.dollar_zero);
|
||||
}
|
||||
|
||||
int uwsgi_rack_init(){
|
||||
|
||||
struct http_status_codes *http_sc;
|
||||
@@ -357,6 +362,10 @@ int uwsgi_rack_init(){
|
||||
|
||||
ruby_script("uwsgi");
|
||||
|
||||
ur.dollar_zero = rb_str_new2("uwsgi");
|
||||
rb_define_hooked_variable("$0", &ur.dollar_zero, 0, rack_hack_dollar_zero);
|
||||
rb_define_hooked_variable("$PROGRAM_NAME", &ur.dollar_zero, 0, rack_hack_dollar_zero);
|
||||
|
||||
ur.signals_protector = rb_ary_new();
|
||||
ur.rpc_protector = rb_ary_new();
|
||||
rb_gc_register_address(&ur.signals_protector);
|
||||
@@ -709,7 +718,7 @@ int uwsgi_rack_request(struct wsgi_request *wsgi_req) {
|
||||
VALUE dws_wr = Data_Wrap_Struct(ur.rb_uwsgi_io_class, 0, 0, wsgi_req);
|
||||
|
||||
if (wsgi_req->async_post) {
|
||||
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(fileno(wsgi_req->async_post)), rb_str_new("r",1) ));
|
||||
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall( rb_const_get(rb_cObject, rb_intern("IO")), rb_intern("new"), 2, INT2NUM(fileno((FILE*)wsgi_req->async_post)), rb_str_new("r",1) ));
|
||||
}
|
||||
else {
|
||||
rb_hash_aset(env, rb_str_new2("rack.input"), rb_funcall(ur.rb_uwsgi_io_class, rb_intern("new"), 1, dws_wr ));
|
||||
|
||||
@@ -52,6 +52,8 @@ struct uwsgi_rack {
|
||||
VALUE signals_protector;
|
||||
VALUE rpc_protector;
|
||||
|
||||
VALUE dollar_zero;
|
||||
|
||||
VALUE dispatcher;
|
||||
VALUE rb_uwsgi_io_class;
|
||||
ID call;
|
||||
|
||||
+3
-3
@@ -195,9 +195,9 @@ static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *
|
||||
else {
|
||||
// add header
|
||||
if (!uwsgi_strncmp("host", 4, key, keylen)) {
|
||||
char *colon = strchr(val, ':');
|
||||
char *colon = memchr(val, ':', vallen);
|
||||
if (colon) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, (colon + 1) - val);
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, vallen - ((colon + 1)-val));
|
||||
}
|
||||
else {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
|
||||
@@ -217,7 +217,7 @@ static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *
|
||||
free(post_filename);
|
||||
}
|
||||
else if (!uwsgi_strncmp("x-forwarded-for", 15, key, keylen)) {
|
||||
char *colon = strchr(val, ',');
|
||||
char *colon = memchr(val, ',', vallen);
|
||||
if (colon) {
|
||||
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - val);
|
||||
}
|
||||
|
||||
+300
-74
@@ -16,7 +16,8 @@ static size_t get_content_length(char *buf, uint16_t size) {
|
||||
return val;
|
||||
}
|
||||
|
||||
void set_http_date(time_t t, char *dst) {
|
||||
|
||||
int set_http_date(time_t t, char *header, int header_len, char *dst, int last) {
|
||||
|
||||
static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
||||
static char *months[] = {
|
||||
@@ -26,12 +27,96 @@ void set_http_date(time_t t, char *dst) {
|
||||
};
|
||||
|
||||
struct tm *hdtm = gmtime(&t);
|
||||
snprintf(dst, 49, "Last-Modified: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n\r\n",
|
||||
|
||||
if (last) {
|
||||
return snprintf(dst, 36+header_len, "%.*s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n\r\n",
|
||||
header_len, header,
|
||||
week[hdtm->tm_wday], hdtm->tm_mday,
|
||||
months[hdtm->tm_mon], hdtm->tm_year+1900,
|
||||
hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
|
||||
}
|
||||
|
||||
return snprintf(dst, 34+header_len, "%.*s: %s, %02d %s %4d %02d:%02d:%02d GMT\r\n",
|
||||
header_len, header,
|
||||
week[hdtm->tm_wday], hdtm->tm_mday,
|
||||
months[hdtm->tm_mon], hdtm->tm_year+1900,
|
||||
hdtm->tm_hour, hdtm->tm_min, hdtm->tm_sec);
|
||||
}
|
||||
|
||||
void uwsgi_add_expires_type(struct wsgi_request *wsgi_req, char *mime_type, int mime_type_len, struct stat *st) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.static_expires_type;
|
||||
time_t now = wsgi_req->start_of_request.tv_sec;
|
||||
// Expires+34+1
|
||||
char expires[42];
|
||||
|
||||
while(udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now+delta, "Expires", 7, expires, 0);
|
||||
if (size > 0) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
udd = uwsgi.static_expires_type_mtime;
|
||||
while(udd) {
|
||||
if (!uwsgi_strncmp(udd->key, udd->keylen, mime_type, mime_type_len)) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime+delta, "Expires", 7, expires, 0);
|
||||
if (size > 0) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
void uwsgi_add_expires(struct wsgi_request *wsgi_req, char *filename, int filename_len, struct stat *st) {
|
||||
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.static_expires;
|
||||
time_t now = wsgi_req->start_of_request.tv_sec;
|
||||
// Expires+34+1
|
||||
char expires[42];
|
||||
|
||||
while(udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(now+delta, "Expires", 7, expires, 0);
|
||||
if (size > 0) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
udd = uwsgi.static_expires_mtime;
|
||||
while(udd) {
|
||||
if (uwsgi_regexp_match(udd->pattern, udd->pattern_extra, filename, filename_len) >= 0) {
|
||||
int delta = uwsgi_str_num(udd->value, udd->vallen);
|
||||
int size = set_http_date(st->st_mtime+delta, "Expires", 7, expires, 0);
|
||||
if (size > 0) {
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, expires, size);
|
||||
wsgi_req->header_cnt++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// only RFC 1123 is supported
|
||||
time_t parse_http_date(char *date, uint16_t len) {
|
||||
|
||||
@@ -916,7 +1001,7 @@ next:
|
||||
udd->vallen = strlen(udd->value);
|
||||
}
|
||||
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len, 0)) {
|
||||
return -1;
|
||||
}
|
||||
nextcs:
|
||||
@@ -944,11 +1029,11 @@ nextcs:
|
||||
if (!real_docroot) goto nextsm;
|
||||
udd->value = real_docroot;
|
||||
udd->vallen = strlen(udd->value);
|
||||
udd->status = 1;
|
||||
udd->status = 1 + uwsgi_is_file(real_docroot);
|
||||
}
|
||||
|
||||
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info+udd->keylen, wsgi_req->path_info_len-udd->keylen)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info+udd->keylen, wsgi_req->path_info_len-udd->keylen, udd->status-1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -956,13 +1041,47 @@ nextsm:
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
// check for static_maps in append mode
|
||||
udd = uwsgi.static_maps2;
|
||||
while(udd) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
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 = uwsgi_malloc(PATH_MAX+1);
|
||||
if (!realpath(udd->value, real_docroot)) {
|
||||
free(real_docroot);
|
||||
udd->value = NULL;
|
||||
}
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
#endif
|
||||
if (!real_docroot) goto nextsm2;
|
||||
udd->value = real_docroot;
|
||||
udd->vallen = strlen(udd->value);
|
||||
udd->status = 1 + uwsgi_is_file(real_docroot);
|
||||
}
|
||||
|
||||
if (!uwsgi_starts_with(wsgi_req->path_info, wsgi_req->path_info_len, udd->key, udd->keylen)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, udd->value, udd->vallen, wsgi_req->path_info, wsgi_req->path_info_len, udd->status-1)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
nextsm2:
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
|
||||
// finally check for docroot
|
||||
if (uwsgi.check_static_docroot && wsgi_req->document_root_len > 0) {
|
||||
char *real_docroot = uwsgi_expand_path(wsgi_req->document_root, wsgi_req->document_root_len, NULL);
|
||||
if (!real_docroot) {
|
||||
return -1;
|
||||
}
|
||||
if (!uwsgi_file_serve(wsgi_req, real_docroot, strlen(real_docroot), wsgi_req->path_info, wsgi_req->path_info_len)) {
|
||||
if (!uwsgi_file_serve(wsgi_req, real_docroot, strlen(real_docroot), wsgi_req->path_info, wsgi_req->path_info_len, 0)) {
|
||||
free(real_docroot);
|
||||
return -1;
|
||||
}
|
||||
@@ -1520,31 +1639,41 @@ char *uwsgi_get_mime_type(char *name, int namelen, int *size) {
|
||||
count++;
|
||||
}
|
||||
|
||||
if (ext) {
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
|
||||
while(udd) {
|
||||
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
|
||||
udd->hits++;
|
||||
// auto optimization
|
||||
if (udd->prev) {
|
||||
if (udd->hits > udd->prev->hits) {
|
||||
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
|
||||
if (udd_parent) {
|
||||
udd_parent->next = udd;
|
||||
}
|
||||
udd_prev->prev = udd;
|
||||
udd_prev->next = udd->next;
|
||||
if (!ext) return NULL;
|
||||
|
||||
udd->prev = udd_parent;
|
||||
udd->next = udd_prev;
|
||||
struct uwsgi_dyn_dict *udd = uwsgi.mimetypes;
|
||||
while(udd) {
|
||||
if (!uwsgi_strncmp(ext, count, udd->key, udd->keylen)) {
|
||||
udd->hits++;
|
||||
// auto optimization
|
||||
if (udd->prev) {
|
||||
if (udd->hits > udd->prev->hits) {
|
||||
struct uwsgi_dyn_dict *udd_parent = udd->prev->prev, *udd_prev = udd->prev;
|
||||
if (udd_parent) {
|
||||
udd_parent->next = udd;
|
||||
}
|
||||
|
||||
if (udd->next) {
|
||||
udd->next->prev = udd_prev;
|
||||
}
|
||||
|
||||
udd_prev->prev = udd;
|
||||
udd_prev->next = udd->next;
|
||||
|
||||
udd->prev = udd_parent;
|
||||
udd->next = udd_prev;
|
||||
|
||||
if (udd->prev == NULL) {
|
||||
uwsgi.mimetypes = udd;
|
||||
}
|
||||
}
|
||||
*size = udd->vallen;
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
*size = udd->vallen;
|
||||
return udd->value;
|
||||
}
|
||||
udd = udd->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -1599,54 +1728,15 @@ int uwsgi_static_stat(char *filename, struct stat *st) {
|
||||
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) {
|
||||
int uwsgi_real_file_serve(struct wsgi_request *wsgi_req, char *real_filename, size_t real_filename_len, struct stat *st) {
|
||||
|
||||
struct stat st;
|
||||
struct iovec headers_vec[8];
|
||||
char real_filename[PATH_MAX+1];
|
||||
|
||||
int mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
|
||||
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("[uwsgi-fileserve] checking for %s\n", filename);
|
||||
#endif
|
||||
if (!realpath(filename, real_filename)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
|
||||
#endif
|
||||
free(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(filename);
|
||||
|
||||
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
|
||||
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!uwsgi_static_stat(real_filename, &st)) {
|
||||
|
||||
real_filename_len = strlen(real_filename);
|
||||
|
||||
// check for skippable ext
|
||||
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
|
||||
while(sse) {
|
||||
if (real_filename_len >= sse->len) {
|
||||
if (!uwsgi_strncmp(real_filename+(real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes_fast(wsgi_req, real_filename, real_filename_len) == UWSGI_ROUTE_BREAK) return 0;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sse = sse->next;
|
||||
}
|
||||
|
||||
int mime_type_size = 0;
|
||||
char http_last_modified[49];
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_lock(&uwsgi.lock_static);
|
||||
#endif
|
||||
@@ -1654,9 +1744,10 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_mutex_unlock(&uwsgi.lock_static);
|
||||
#endif
|
||||
|
||||
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) {
|
||||
if (st->st_mtime <= ims) {
|
||||
wsgi_req->status = 304;
|
||||
headers_vec[0].iov_base = wsgi_req->protocol;
|
||||
headers_vec[0].iov_len = wsgi_req->protocol_len;
|
||||
@@ -1703,6 +1794,10 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
ah = ah->next;
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
uwsgi_add_expires(wsgi_req, real_filename, real_filename_len, st);
|
||||
#endif
|
||||
|
||||
// Content-Type (if available)
|
||||
if (mime_type_size > 0 && mime_type) {
|
||||
headers_vec[0].iov_base = "Content-Type: ";
|
||||
@@ -1713,6 +1808,9 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
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++;
|
||||
|
||||
// check for content-type related headers
|
||||
uwsgi_add_expires_type(wsgi_req, mime_type, mime_type_size, st);
|
||||
}
|
||||
|
||||
// nginx
|
||||
@@ -1722,7 +1820,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
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);
|
||||
set_http_date(st->st_mtime, "Last-Modified", 13, http_last_modified, 1);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
wsgi_req->header_cnt += 2;
|
||||
}
|
||||
@@ -1733,7 +1831,7 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
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);
|
||||
set_http_date(st->st_mtime, "Last-Modified", 13, http_last_modified, 1);
|
||||
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, http_last_modified, 48);
|
||||
wsgi_req->header_cnt += 2;
|
||||
}
|
||||
@@ -1742,12 +1840,12 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
// 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_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);
|
||||
set_http_date(st->st_mtime, "Last-Modified", 13, http_last_modified, 1);
|
||||
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);
|
||||
@@ -1761,6 +1859,134 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
|
||||
|
||||
wsgi_req->status = 200;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *uwsgi_static_offload_thread(void *req) {
|
||||
|
||||
struct uwsgi_offload_request *uof_req = (struct uwsgi_offload_request *) req;
|
||||
|
||||
uwsgi_real_file_serve(&uof_req->wsgi_req, uof_req->real_filename, uof_req->real_filename_len, &uof_req->st);
|
||||
|
||||
// close the connection with the webserver
|
||||
if (!uof_req->wsgi_req.fd_closed || !uof_req->wsgi_req.body_as_file) {
|
||||
// NOTE, if we close the socket before receiving eventually sent data, socket layer will send a RST
|
||||
uof_req->wsgi_req.socket->proto_close(&uof_req->wsgi_req);
|
||||
}
|
||||
|
||||
// free buffer
|
||||
free(uof_req->buffer);
|
||||
// free hvec
|
||||
free(uof_req->hvec);
|
||||
free(uof_req);
|
||||
|
||||
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
|
||||
uwsgi.workers[uwsgi.mywid].static_offload_threads--;
|
||||
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
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, int is_a_file) {
|
||||
|
||||
struct stat st;
|
||||
char real_filename[PATH_MAX+1];
|
||||
size_t real_filename_len = 0;
|
||||
char *filename = NULL;
|
||||
|
||||
|
||||
if (!is_a_file) {
|
||||
filename = uwsgi_concat3n(document_root, document_root_len, "/", 1, path_info, path_info_len);
|
||||
}
|
||||
else {
|
||||
filename = uwsgi_concat2n(document_root, document_root_len, "", 0);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] checking for %s\n", filename);
|
||||
#endif
|
||||
if (!realpath(filename, real_filename)) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-fileserve] unable to get realpath() of the static file\n");
|
||||
#endif
|
||||
free(filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
free(filename);
|
||||
|
||||
if (uwsgi_starts_with(real_filename, strlen(real_filename), document_root, document_root_len)) {
|
||||
uwsgi_log("[uwsgi-fileserve] security error: %s is not under %.*s\n", real_filename, document_root_len, document_root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!uwsgi_static_stat(real_filename, &st)) {
|
||||
|
||||
real_filename_len = strlen(real_filename);
|
||||
|
||||
// check for skippable ext
|
||||
struct uwsgi_string_list *sse = uwsgi.static_skip_ext;
|
||||
while(sse) {
|
||||
if (real_filename_len >= sse->len) {
|
||||
if (!uwsgi_strncmp(real_filename+(real_filename_len - sse->len), sse->len, sse->value, sse->len)) {
|
||||
#ifdef UWSGI_ROUTING
|
||||
if (uwsgi_apply_routes_fast(wsgi_req, real_filename, real_filename_len) == UWSGI_ROUTE_BREAK) return 0;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
sse = sse->next;
|
||||
}
|
||||
|
||||
// Ok, the file must be served as static from uWSGI
|
||||
if (uwsgi.static_offload_to_thread) {
|
||||
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
|
||||
uint64_t offload_thread_count = uwsgi.workers[uwsgi.mywid].static_offload_threads;
|
||||
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
|
||||
|
||||
if (offload_thread_count > (uint64_t) uwsgi.static_offload_to_thread) {
|
||||
uwsgi_log_verbose("OVERLOAD !!! unable to offload static file serving\n");
|
||||
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
|
||||
}
|
||||
|
||||
struct uwsgi_offload_request *uor = uwsgi_malloc(sizeof(struct uwsgi_offload_request));
|
||||
|
||||
// buffer
|
||||
uor->buffer = uwsgi_malloc(uwsgi.buffer_size); memcpy(uor->buffer, wsgi_req->buffer, uwsgi.buffer_size);
|
||||
// iovec
|
||||
uor->hvec = uwsgi_malloc(sizeof(struct iovec) * uwsgi.vec_size); memcpy(uor->hvec, wsgi_req->hvec, sizeof(struct iovec) * uwsgi.vec_size);
|
||||
|
||||
// wsgi_req
|
||||
memcpy(&uor->wsgi_req, wsgi_req, sizeof(struct wsgi_request));
|
||||
|
||||
uor->wsgi_req.buffer = uor->buffer;
|
||||
uor->wsgi_req.hvec = uor->hvec;
|
||||
|
||||
// stat
|
||||
memcpy(&uor->st, &st, sizeof(struct stat));
|
||||
|
||||
// filename
|
||||
memcpy(uor->real_filename, real_filename, real_filename_len);
|
||||
uor->real_filename_len = real_filename_len;
|
||||
|
||||
// avoid closing the connection
|
||||
wsgi_req->fd_closed = 1;
|
||||
|
||||
pthread_mutex_lock(&uwsgi.static_offload_thread_lock);
|
||||
uwsgi.workers[uwsgi.mywid].static_offload_threads++;
|
||||
pthread_mutex_unlock(&uwsgi.static_offload_thread_lock);
|
||||
|
||||
if (pthread_create(&uor->tid, &uwsgi.static_offload_thread_attr, uwsgi_static_offload_thread, (void *) uor)) {
|
||||
uwsgi_error("pthread_create()");
|
||||
// bad condition, better to exit...
|
||||
exit(1);
|
||||
}
|
||||
wsgi_req->status = -30;
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return uwsgi_real_file_serve(wsgi_req, real_filename, real_filename_len, &st);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
from threading import Thread
|
||||
import time
|
||||
import uwsgi
|
||||
|
||||
def mess():
|
||||
while True:
|
||||
for i in xrange(0, 100):
|
||||
if uwsgi.ready():
|
||||
uwsgi.signal(17)
|
||||
print(i)
|
||||
time.sleep(0.1)
|
||||
|
||||
|
||||
@@ -559,3 +559,33 @@ cycle:
|
||||
return received_signal;
|
||||
}
|
||||
|
||||
void uwsgi_receive_signal(int fd, char *name, int id) {
|
||||
|
||||
uint8_t uwsgi_signal;
|
||||
|
||||
ssize_t ret = read(fd, &uwsgi_signal, 1);
|
||||
|
||||
if (ret == 0) {
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
|
||||
uwsgi_error("[uwsgi-signal] read()");
|
||||
goto destroy;
|
||||
}
|
||||
else if (ret > 0) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to %s %d\n", uwsgi_signal, name, id);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on %s %d\n", uwsgi_signal, name, id);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
destroy:
|
||||
// better to kill the whole worker...
|
||||
uwsgi_log_verbose("uWSGI %s %d screams: UAAAAAAH my master disconnected: i will kill myself !!!\n", name, id);
|
||||
end_me(0);
|
||||
|
||||
}
|
||||
|
||||
@@ -758,6 +758,7 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
return serverfd;
|
||||
}
|
||||
|
||||
// set non-blocking socket
|
||||
void uwsgi_socket_nb(int fd) {
|
||||
int arg;
|
||||
|
||||
@@ -774,6 +775,24 @@ void uwsgi_socket_nb(int fd) {
|
||||
|
||||
}
|
||||
|
||||
// set blocking socket
|
||||
void uwsgi_socket_b(int fd) {
|
||||
int arg;
|
||||
|
||||
arg = fcntl(fd, F_GETFL, NULL);
|
||||
if (arg < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
return;
|
||||
}
|
||||
arg &= (~O_NONBLOCK);
|
||||
if (fcntl(fd, F_SETFL, arg) < 0) {
|
||||
uwsgi_error("fcntl()");
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_size, int timeout, int async) {
|
||||
|
||||
int arg, ret;
|
||||
@@ -1013,10 +1032,6 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
|
||||
union uwsgi_sockaddr usa;
|
||||
int abstract = 0;
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("creating socket from fd %d\n", fd);
|
||||
#endif
|
||||
|
||||
socket_type_len = sizeof(struct sockaddr_un);
|
||||
gsa.sa = &usa.sa;
|
||||
if (!getsockname(fd, gsa.sa, &socket_type_len)) {
|
||||
|
||||
@@ -340,19 +340,7 @@ void spooler(struct uwsgi_spooler *uspool) {
|
||||
if (event_queue_wait(spooler_event_queue, timeout, &interesting_fd) > 0) {
|
||||
if (uwsgi.master_process) {
|
||||
if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
|
||||
uint8_t uwsgi_signal;
|
||||
if (read(interesting_fd, &uwsgi_signal, 1) <= 0) {
|
||||
uwsgi_log_verbose("uWSGI spooler screams: UAAAAAAH my master died, i will follow him...\n");
|
||||
end_me(0);
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to the spooler\n", uwsgi_signal);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on the spooler\n", uwsgi_signal);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(interesting_fd, "spooler", (int) getpid());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
# uwsgi -s :3031 -M -p 4 --plugin gevent --loop gevent --async 1000 --enable-threads -w tests.testgevent
|
||||
from threading import Thread
|
||||
import gevent
|
||||
import uwsgi
|
||||
import time
|
||||
|
||||
def microtask(wid):
|
||||
print "i am a gevent task"
|
||||
gevent.sleep(10)
|
||||
print "10 seconds elapsed in worker id %d" % wid
|
||||
|
||||
def athread():
|
||||
while True:
|
||||
time.sleep(1)
|
||||
print "i am the thread 1"
|
||||
|
||||
def athread2():
|
||||
while True:
|
||||
time.sleep(1)
|
||||
print "i am the thread 2"
|
||||
|
||||
t1 = Thread(target=athread)
|
||||
t1.daemon = True
|
||||
t1.start()
|
||||
|
||||
t2 = Thread(target=athread2)
|
||||
t2.daemon = True
|
||||
t2.start()
|
||||
|
||||
def application(environ, start_response):
|
||||
|
||||
gevent.sleep()
|
||||
start_response('200 OK', [('Content-Type','text/html')])
|
||||
yield "sleeping for 3 seconds...<br/>"
|
||||
gevent.sleep(3)
|
||||
yield "done<br/>"
|
||||
gevent.spawn(microtask, uwsgi.worker_id())
|
||||
yield "microtask started<br/>"
|
||||
|
||||
@@ -1018,7 +1018,6 @@ int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
|
||||
|
||||
int ret;
|
||||
int interesting_fd;
|
||||
char uwsgi_signal;
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
thunder_lock;
|
||||
@@ -1037,23 +1036,7 @@ int wsgi_req_accept(int queue, struct wsgi_request *wsgi_req) {
|
||||
|
||||
thunder_unlock;
|
||||
|
||||
if (read(interesting_fd, &uwsgi_signal, 1) <= 0) {
|
||||
if (uwsgi.no_orphans) {
|
||||
uwsgi_log_verbose("uWSGI worker %d screams: UAAAAAAH my master died, i will follow him...\n", uwsgi.mywid);
|
||||
end_me(0);
|
||||
}
|
||||
else {
|
||||
close(interesting_fd);
|
||||
}
|
||||
}
|
||||
else {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
#endif
|
||||
if (uwsgi_signal_handler(uwsgi_signal)) {
|
||||
uwsgi_log_verbose("error managing signal %d on worker %d\n", uwsgi_signal, uwsgi.mywid);
|
||||
}
|
||||
}
|
||||
uwsgi_receive_signal(interesting_fd, "worker", uwsgi.mywid);
|
||||
|
||||
#ifdef UWSGI_THREADING
|
||||
if (uwsgi.threads > 1) pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &ret);
|
||||
@@ -1135,6 +1118,11 @@ void sanitize_args() {
|
||||
uwsgi.ignore_sigpipe = 1;
|
||||
uwsgi.ignore_write_errors = 1;
|
||||
}
|
||||
|
||||
if (uwsgi.cheaper_count > 0 && uwsgi.cheaper_count >= uwsgi.numproc) {
|
||||
uwsgi_log("invalid cheaper value: must be lower than processes\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void env_to_arg(char *src, char *dst) {
|
||||
@@ -1925,6 +1913,22 @@ int uwsgi_logic_opt_if_not_env(char *key, char *value) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_reload(char *key, char *value) {
|
||||
if (uwsgi.is_a_reload) {
|
||||
add_exported_option(key, value, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_not_reload(char *key, char *value) {
|
||||
if (!uwsgi.is_a_reload) {
|
||||
add_exported_option(key, value, 0);
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_logic_opt_if_file(char *key, char *value) {
|
||||
|
||||
if (uwsgi_is_file(uwsgi.logic_opt_data)) {
|
||||
@@ -3190,6 +3194,7 @@ struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **list,
|
||||
uwsgi_string->len = strlen(value);
|
||||
}
|
||||
uwsgi_string->next = NULL;
|
||||
uwsgi_string->custom = 0;
|
||||
|
||||
return uwsgi_string;
|
||||
}
|
||||
@@ -3920,7 +3925,11 @@ void uwsgi_set_processname(char *name) {
|
||||
strncat(uwsgi.orig_argv[0], uwsgi.procname_append, uwsgi.max_procname-(amount+1));
|
||||
}
|
||||
|
||||
memset(uwsgi.orig_argv[0]+amount+1, ' ', uwsgi.max_procname-(amount-1));
|
||||
// fill with spaces...
|
||||
memset(uwsgi.orig_argv[0]+amount+1, ' ', uwsgi.max_procname-(amount));
|
||||
// end with \0
|
||||
memset(uwsgi.orig_argv[0]+amount+1+(uwsgi.max_procname-(amount)), '\0', 1);
|
||||
|
||||
#elif defined(__FreeBSD__)
|
||||
if (uwsgi.procname_prefix) {
|
||||
if (!uwsgi.procname_append) {
|
||||
@@ -4088,6 +4097,10 @@ char *uwsgi_check_touches(struct uwsgi_string_list *touch_list) {
|
||||
else {
|
||||
if (!touch->custom) touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
if ((uint64_t) tr_st.st_mtime > touch->custom) {
|
||||
#ifdef UWSGI_DEBUG
|
||||
uwsgi_log("[uwsgi-check-touches] modification detected on %s: %llu -> %llu\n", touch->value, (unsigned long long) touch->custom,
|
||||
(unsigned long long) tr_st.st_mtime);
|
||||
#endif
|
||||
touch->custom = (uint64_t) tr_st.st_mtime;
|
||||
return touch->value;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"xmlconfig", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"xml", required_argument, 'x', "load config from xml file", uwsgi_opt_load_xml, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
|
||||
{"skip-zero", no_argument, 0, "skip check of file descriptor 0", uwsgi_opt_true, &uwsgi.skip_zero,0},
|
||||
|
||||
{"set", required_argument, 'S', "set a custom placeholder", uwsgi_opt_set_placeholder, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"for", required_argument, 0, "(opt logic) for cycle", uwsgi_opt_logic, (void *) uwsgi_logic_opt_for, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -68,6 +71,9 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"if-not-env", required_argument, 0, "(opt logic) check for environment variable", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_env, UWSGI_OPT_IMMEDIATE},
|
||||
{"ifenv", required_argument, 0, "(opt logic) check for environment variable", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_env, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_reload, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-reload", no_argument, 0, "(opt logic) check for reload", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_reload, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
{"if-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
|
||||
{"if-not-exists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_not_exists, UWSGI_OPT_IMMEDIATE},
|
||||
{"ifexists", required_argument, 0, "(opt logic) check for file/directory existance", uwsgi_opt_logic, (void *) uwsgi_logic_opt_if_exists, UWSGI_OPT_IMMEDIATE},
|
||||
@@ -260,7 +266,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"propagate-touch", no_argument, 0, "over-engineering option for system with flaky signal mamagement", uwsgi_opt_true, &uwsgi.propagate_touch, 0},
|
||||
{"limit-post", required_argument, 0, "limit request body", uwsgi_opt_set_64bit, &uwsgi.limit_post, 0},
|
||||
{"no-orphans", no_argument, 0, "automatically kill workers if master dies (can be dangerous for availability)", uwsgi_opt_true, &uwsgi.no_orphans, 0},
|
||||
{"prio", required_argument, 0, "set processes/threads priority", uwsgi_opt_set_int, &uwsgi.prio, 0},
|
||||
{"prio", required_argument, 0, "set processes/threads priority", uwsgi_opt_set_rawint, &uwsgi.prio, 0},
|
||||
{"cpu-affinity", required_argument, 0, "set cpu affinity", uwsgi_opt_set_int, &uwsgi.cpu_affinity, 0},
|
||||
{"post-buffering", required_argument, 0, "enable post buffering", uwsgi_opt_set_64bit, &uwsgi.post_buffering, 0},
|
||||
{"post-buffering-bufsize", required_argument, 0, "set buffer size for read() in post buffering mode", uwsgi_opt_set_64bit, &uwsgi.post_buffering_bufsize,0},
|
||||
@@ -363,22 +369,35 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"route-qs", required_argument, 0, "add a route based on QUERY_STRING", uwsgi_opt_add_route, "query_string", 0},
|
||||
#endif
|
||||
{"add-header", required_argument, 0, "automatically add HTTP headers to response", uwsgi_opt_add_string_list, &uwsgi.additional_headers, 0},
|
||||
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, 0},
|
||||
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, UWSGI_OPT_MIME},
|
||||
{"static-check", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, 0},
|
||||
{"static-map", required_argument, 0, "map mountpoint to static directory", uwsgi_opt_static_map, NULL, 0},
|
||||
{"static-skip-ext", required_argument, 0, "skip specified extension from staticfile checks", uwsgi_opt_add_string_list, &uwsgi.static_skip_ext, 0},
|
||||
{"static-index", required_argument, 0, "search for specified file if a directory is requested", uwsgi_opt_add_string_list, &uwsgi.static_index, 0},
|
||||
{"mimefile", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_set_str, &uwsgi.mime_file, 0},
|
||||
{"mime-file", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_set_str, &uwsgi.mime_file, 0},
|
||||
|
||||
{"file-serve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL,0},
|
||||
{"fileserve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL,0},
|
||||
{"check-static", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
{"check-static-docroot", no_argument, 0, "check for static files in the requested DOCUMENT_ROOT", uwsgi_opt_true, &uwsgi.check_static_docroot, UWSGI_OPT_MIME},
|
||||
{"static-check", required_argument, 0, "check for static files in the specified directory", uwsgi_opt_check_static, NULL, UWSGI_OPT_MIME},
|
||||
{"static-map", required_argument, 0, "map mountpoint to static directory (or file)", uwsgi_opt_static_map, &uwsgi.static_maps, UWSGI_OPT_MIME},
|
||||
{"static-map2", required_argument, 0, "like static-map but completely appending the requested resource to the docroot", uwsgi_opt_static_map, &uwsgi.static_maps2, UWSGI_OPT_MIME},
|
||||
{"static-skip-ext", required_argument, 0, "skip specified extension from staticfile checks", uwsgi_opt_add_string_list, &uwsgi.static_skip_ext, UWSGI_OPT_MIME},
|
||||
{"static-index", required_argument, 0, "search for specified file if a directory is requested", uwsgi_opt_add_string_list, &uwsgi.static_index, UWSGI_OPT_MIME},
|
||||
{"mimefile", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
{"mime-file", required_argument, 0, "set mime types file path (default /etc/mime.types)", uwsgi_opt_add_string_list, &uwsgi.mime_file, UWSGI_OPT_MIME},
|
||||
|
||||
{"static-expires-type", required_argument, 0, "set the Expires header based on content type", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type, UWSGI_OPT_MIME},
|
||||
{"static-expires-type-mtime", required_argument, 0, "set the Expires header based on content type and file mtime", uwsgi_opt_add_dyn_dict, &uwsgi.static_expires_type_mtime, UWSGI_OPT_MIME},
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
{"static-expires", required_argument, 0, "set the Expires header based on filename regexp", uwsgi_opt_add_regexp_dyn_dict, &uwsgi.static_expires, UWSGI_OPT_MIME},
|
||||
{"static-expires-mtime", required_argument, 0, "set the Expires header based on filename regexp and file mtime", uwsgi_opt_add_regexp_dyn_dict, &uwsgi.static_expires_mtime, UWSGI_OPT_MIME},
|
||||
#endif
|
||||
|
||||
{"static-offload-to-thread", required_argument, 0, "offload static file serving to a thread (upto the specified number of threads)", uwsgi_opt_set_int, &uwsgi.static_offload_to_thread, UWSGI_OPT_MIME},
|
||||
|
||||
{"file-serve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
|
||||
{"fileserve-mode", required_argument, 0, "set static file serving mode", uwsgi_opt_fileserve_mode, NULL, UWSGI_OPT_MIME},
|
||||
|
||||
{"check-cache", no_argument, 0, "check for response data in the cache", uwsgi_opt_true, &uwsgi.check_cache, 0},
|
||||
{"close-on-exec", no_argument, 0, "set close-on-exec on sockets (could be required for spawning processes in requests)", uwsgi_opt_true, &uwsgi.close_on_exec, 0},
|
||||
{"mode", required_argument, 0, "set uWSGI custom mode", uwsgi_opt_set_str, &uwsgi.mode,0},
|
||||
{"env", required_argument, 0, "set environment variable", uwsgi_opt_set_env, NULL, 0},
|
||||
{"unenv", required_argument, 0, "unset environment variable", uwsgi_opt_unset_env, NULL, 0},
|
||||
{"vacuum", no_argument, 0, "try to remove all of the generated file/sockets", uwsgi_opt_true, &uwsgi.vacuum,0},
|
||||
#ifdef __linux__
|
||||
{"cgroup", required_argument, 0, "put the processes in the specified cgroup", uwsgi_opt_add_string_list, &uwsgi.cgroup,0},
|
||||
@@ -547,8 +566,8 @@ void gracefully_kill(int signum) {
|
||||
uwsgi_log("Gracefully killing worker %d (pid: %d)...\n", uwsgi.mywid, uwsgi.mypid);
|
||||
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
|
||||
#ifdef UWSGI_THREADING
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
if (uwsgi.threads > 1) {
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
wait_for_threads();
|
||||
if (!uwsgi.core[wsgi_req->async_id]->in_request) {
|
||||
exit(UWSGI_RELOAD_CODE);
|
||||
@@ -1341,7 +1360,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi.shared->worker_log_pipe[0] = -1;
|
||||
uwsgi.shared->worker_log_pipe[1] = -1;
|
||||
|
||||
uwsgi.mime_file = "/etc/mime.types";
|
||||
|
||||
#ifdef UWSGI_BLACKLIST
|
||||
if (!uwsgi_file_to_string_list(UWSGI_BLACKLIST, &uwsgi.blacklist)) {
|
||||
@@ -1640,6 +1658,12 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
uwsgi_log_initial("*** big endian arch detected ***\n");
|
||||
#endif
|
||||
|
||||
#if defined(_SC_NPROCESSORS_ONLN)
|
||||
uwsgi_log_initial("detected number of CPU cores: %d\n", sysconf(_SC_NPROCESSORS_ONLN));
|
||||
#elif defined(_SC_NPROCESSORS_CONF)
|
||||
uwsgi_log_initial("detected number of CPU cores: %d\n", sysconf(_SC_NPROCESSORS_CONF));
|
||||
#endif
|
||||
|
||||
|
||||
uwsgi_log_initial("current working directory: %s\n", uwsgi.cwd);
|
||||
|
||||
@@ -1850,13 +1874,27 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
// initialize workers
|
||||
|
||||
|
||||
if (uwsgi.build_mime_dict) {
|
||||
if (!access(uwsgi.mime_file, R_OK)) {
|
||||
uwsgi_build_mime_dict(uwsgi.mime_file);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("!!! no mime.types file found !!!\n");
|
||||
if (!uwsgi.mime_file) uwsgi_string_new_list(&uwsgi.mime_file, "/etc/mime.types");
|
||||
struct uwsgi_string_list *umd = uwsgi.mime_file;
|
||||
while(umd) {
|
||||
if (!access(umd->value, R_OK)) {
|
||||
uwsgi_build_mime_dict(umd->value);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("!!! no %s file found !!!\n", umd->value);
|
||||
}
|
||||
umd = umd->next;
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.static_offload_to_thread) {
|
||||
pthread_attr_init(&uwsgi.static_offload_thread_attr);
|
||||
pthread_attr_setdetachstate(&uwsgi.static_offload_thread_attr, PTHREAD_CREATE_DETACHED);
|
||||
// 512K should be enough...
|
||||
pthread_attr_setstacksize(&uwsgi.static_offload_thread_attr, 512*1024);
|
||||
pthread_mutex_init(&uwsgi.static_offload_thread_lock, NULL);
|
||||
}
|
||||
|
||||
// end of generic initialization
|
||||
@@ -1930,7 +1968,7 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
if (!getrlimit(RLIMIT_NOFILE, &uwsgi.rl)) {
|
||||
uwsgi.max_fd = uwsgi.rl.rlim_cur;
|
||||
uwsgi_log("detected max file descriptor number: %d\n", (int) uwsgi.max_fd);
|
||||
uwsgi_log_initial("detected max file descriptor number: %d\n", (int) uwsgi.max_fd);
|
||||
}
|
||||
|
||||
uwsgi.wsgi_requests = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.cores);
|
||||
@@ -2050,10 +2088,9 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!uwsgi.no_server) {
|
||||
|
||||
// systemd socket activation
|
||||
// systemd/upstart/zerg socket activation
|
||||
if (!uwsgi.is_a_reload) {
|
||||
char *listen_pid = getenv("LISTEN_PID");
|
||||
if (listen_pid) {
|
||||
@@ -2062,20 +2099,33 @@ int uwsgi_start(void *v_argv) {
|
||||
if (listen_fds) {
|
||||
int systemd_fds = atoi(listen_fds);
|
||||
if (systemd_fds > 0) {
|
||||
uwsgi_log("- SystemD socket activation detected -\n");
|
||||
for(i=3;i<3+systemd_fds;i++) {
|
||||
uwsgi_sock = uwsgi_new_socket(NULL);
|
||||
uwsgi_add_socket_from_fd(uwsgi_sock, i);
|
||||
}
|
||||
uwsgi.skip_zero = 1;
|
||||
}
|
||||
unsetenv("LISTEN_PID");
|
||||
unsetenv("LISTEN_FDS");
|
||||
goto skipzero;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!uwsgi.is_a_reload) {
|
||||
char *upstart_events = getenv("UPSTART_EVENTS");
|
||||
if (upstart_events && !strcmp(upstart_events, "socket")) {
|
||||
char *upstart_fds = getenv("UPSTART_FDS");
|
||||
if (upstart_fds) {
|
||||
uwsgi_log("- Upstart socket bridge detected (job: %s) -\n", getenv("UPSTART_JOB"));
|
||||
uwsgi_sock = uwsgi_new_socket(NULL);
|
||||
uwsgi_add_socket_from_fd(uwsgi_sock, atoi(upstart_fds));
|
||||
uwsgi.skip_zero = 1;
|
||||
}
|
||||
unsetenv("UPSTART_EVENTS");
|
||||
unsetenv("UPSTART_FDS");
|
||||
}
|
||||
|
||||
|
||||
struct uwsgi_string_list *zn = uwsgi.zerg_node;
|
||||
while (zn) {
|
||||
if (uwsgi_zerg_attach(zn->value)) {
|
||||
@@ -2108,6 +2158,7 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//check for inherited sockets
|
||||
if (uwsgi.is_a_reload) {
|
||||
|
||||
@@ -2197,6 +2248,8 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//now bind all the unbound sockets
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -2237,6 +2290,7 @@ int uwsgi_start(void *v_argv) {
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
|
||||
if (uwsgi.chown_socket) {
|
||||
if (!uwsgi.master_as_root) {
|
||||
uwsgi_as_root();
|
||||
@@ -2256,7 +2310,7 @@ int uwsgi_start(void *v_argv) {
|
||||
if (!zero_used) {
|
||||
socket_type_len = sizeof(struct sockaddr_un);
|
||||
gsa.sa = (struct sockaddr *) &usa;
|
||||
if (!getsockname(0, gsa.sa, &socket_type_len)) {
|
||||
if (!uwsgi.skip_zero && !getsockname(0, gsa.sa, &socket_type_len)) {
|
||||
if (gsa.sa->sa_family == AF_UNIX) {
|
||||
uwsgi_sock = uwsgi_new_socket(usa.sa_un.sun_path);
|
||||
uwsgi_sock->family = AF_UNIX;
|
||||
@@ -2294,8 +2348,6 @@ int uwsgi_start(void *v_argv) {
|
||||
|
||||
}
|
||||
|
||||
skipzero:
|
||||
|
||||
// check for auto_port socket
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
@@ -3488,8 +3540,24 @@ void uwsgi_opt_set_int(char *opt, char *value, void *key) {
|
||||
else {
|
||||
*ptr = 1;
|
||||
}
|
||||
|
||||
if (*ptr < 0) {
|
||||
uwsgi_log("invalid value for option \"%s\": must be > 0\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_rawint(char *opt, char *value, void *key) {
|
||||
int *ptr = (int *) key;
|
||||
if (value) {
|
||||
*ptr = atoi((char *)value);
|
||||
}
|
||||
else {
|
||||
*ptr = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_set_64bit(char *opt, char *value, void *key) {
|
||||
uint64_t *ptr = (uint64_t *) key;
|
||||
|
||||
@@ -3644,6 +3712,12 @@ void uwsgi_opt_set_env(char *opt, char *value, void *none) {
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_unset_env(char *opt, char *value, void *none) {
|
||||
if (unsetenv(value)) {
|
||||
uwsgi_error("unsetenv()");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_opt_pidfile_signal(char *opt, char *pidfile, void *sig) {
|
||||
|
||||
long *signum_fake_ptr = (long *) sig;
|
||||
@@ -3689,6 +3763,44 @@ void uwsgi_opt_check_static(char *opt, char *value, void *foobar) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_add_dyn_dict(char *opt, char *value, void *dict) {
|
||||
|
||||
char *equal = strchr(value, '=');
|
||||
if (!equal) {
|
||||
uwsgi_log("invalid dictionary syntax for %s\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_dyn_dict **udd = (struct uwsgi_dyn_dict **) dict;
|
||||
|
||||
uwsgi_dyn_dict_new(udd, value, equal-value, equal+1, strlen(equal+1));
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
void uwsgi_opt_add_regexp_dyn_dict(char *opt, char *value, void *dict) {
|
||||
|
||||
char *space = strchr(value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid dictionary syntax for %s\n", opt);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
struct uwsgi_dyn_dict **udd = (struct uwsgi_dyn_dict **) dict;
|
||||
|
||||
struct uwsgi_dyn_dict *new_udd = uwsgi_dyn_dict_new(udd, value, space-value, space+1, strlen(space+1));
|
||||
|
||||
char *regexp = uwsgi_concat2n(value, space-value, "", 0);
|
||||
|
||||
if (uwsgi_regexp_build(regexp, &new_udd->pattern, &new_udd->pattern_extra)) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
free(regexp);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void uwsgi_opt_fileserve_mode(char *opt, char *value, void *foobar) {
|
||||
|
||||
if (!strcasecmp("x-sendfile", value)) {
|
||||
@@ -3709,16 +3821,20 @@ void uwsgi_opt_fileserve_mode(char *opt, char *value, void *foobar) {
|
||||
|
||||
}
|
||||
|
||||
void uwsgi_opt_static_map(char *opt, char *value, void *foobar) {
|
||||
void uwsgi_opt_static_map(char *opt, char *value, void *static_maps) {
|
||||
|
||||
struct uwsgi_dyn_dict **maps = (struct uwsgi_dyn_dict **) static_maps;
|
||||
char *mountpoint = uwsgi_str(value);
|
||||
char *docroot = strchr(mountpoint, '=');
|
||||
|
||||
char *docroot = strchr(mountpoint, '=');
|
||||
|
||||
if (!docroot) {
|
||||
uwsgi_log("invalid document root in static map, syntax mountpoint=docroot\n");
|
||||
exit(1);
|
||||
}
|
||||
docroot[0] = 0;
|
||||
docroot++;
|
||||
uwsgi_dyn_dict_new(&uwsgi.static_maps, mountpoint, strlen(mountpoint), docroot, strlen(docroot));
|
||||
uwsgi_dyn_dict_new(maps, mountpoint, strlen(mountpoint), docroot, strlen(docroot));
|
||||
uwsgi_log("[uwsgi-static] added mapping for %s => %s\n", mountpoint, docroot);
|
||||
uwsgi.build_mime_dict = 1;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ extern "C" {
|
||||
#define uwsgi_str(x) uwsgi_concat2(x, "")
|
||||
|
||||
#define uwsgi_notify(x) if (uwsgi.notify) uwsgi.notify(x)
|
||||
#define uwsgi_notify_ready() if (uwsgi.notify_ready) uwsgi.notify_ready()
|
||||
#define uwsgi_notify_ready() uwsgi.shared->ready = 1 ; if (uwsgi.notify_ready) uwsgi.notify_ready()
|
||||
|
||||
#define uwsgi_apps uwsgi.workers[uwsgi.mywid].apps
|
||||
#define uwsgi_apps_cnt uwsgi.workers[uwsgi.mywid].apps_cnt
|
||||
@@ -334,6 +334,9 @@ struct uwsgi_lock_ops {
|
||||
#define uwsgi_wlock(x) uwsgi.lock_ops.wlock(x)
|
||||
#define uwsgi_rwunlock(x) uwsgi.lock_ops.rwunlock(x)
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
#include <pcre.h>
|
||||
#endif
|
||||
|
||||
struct uwsgi_dyn_dict {
|
||||
|
||||
@@ -345,6 +348,11 @@ struct uwsgi_dyn_dict {
|
||||
uint64_t hits;
|
||||
int status;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
pcre *pattern;
|
||||
pcre_extra *pattern_extra;
|
||||
#endif
|
||||
|
||||
struct uwsgi_dyn_dict *prev;
|
||||
struct uwsgi_dyn_dict *next;
|
||||
};
|
||||
@@ -647,7 +655,6 @@ struct uwsgi_plugin {
|
||||
};
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
#include <pcre.h>
|
||||
int uwsgi_regexp_build(char *, pcre **, pcre_extra **);
|
||||
int uwsgi_regexp_match(pcre *, pcre_extra *, char *, int);
|
||||
int uwsgi_regexp_match_ovec(pcre *, pcre_extra *, char *, int, int *, int);
|
||||
@@ -1247,7 +1254,8 @@ struct uwsgi_server {
|
||||
// static file serving
|
||||
int file_serve_mode;
|
||||
int build_mime_dict;
|
||||
char *mime_file;
|
||||
|
||||
struct uwsgi_string_list *mime_file;
|
||||
|
||||
struct uwsgi_probe *probes;
|
||||
|
||||
@@ -1270,11 +1278,22 @@ struct uwsgi_server {
|
||||
int daemons_cnt;
|
||||
|
||||
struct uwsgi_dyn_dict *static_maps;
|
||||
struct uwsgi_dyn_dict *static_maps2;
|
||||
struct uwsgi_dyn_dict *check_static;
|
||||
struct uwsgi_dyn_dict *mimetypes;
|
||||
struct uwsgi_string_list *static_skip_ext;
|
||||
struct uwsgi_string_list *static_index;
|
||||
|
||||
struct uwsgi_dyn_dict *static_expires_type;
|
||||
struct uwsgi_dyn_dict *static_expires_type_mtime;
|
||||
|
||||
struct uwsgi_dyn_dict *static_expires;
|
||||
struct uwsgi_dyn_dict *static_expires_mtime;
|
||||
|
||||
int check_static_docroot;
|
||||
int static_offload_to_thread;
|
||||
pthread_attr_t static_offload_thread_attr;
|
||||
pthread_mutex_t static_offload_thread_lock;
|
||||
|
||||
char *daemonize;
|
||||
char *daemonize2;
|
||||
@@ -1461,6 +1480,7 @@ struct uwsgi_server {
|
||||
|
||||
|
||||
int no_orphans;
|
||||
int skip_zero;
|
||||
|
||||
char *chdir;
|
||||
char *chdir2;
|
||||
@@ -1634,6 +1654,17 @@ struct uwsgi_server {
|
||||
|
||||
};
|
||||
|
||||
struct uwsgi_offload_request {
|
||||
pthread_t tid;
|
||||
struct wsgi_request wsgi_req;
|
||||
char *buffer;
|
||||
struct iovec *hvec;
|
||||
char real_filename[PATH_MAX+1];
|
||||
size_t real_filename_len;
|
||||
struct stat st;
|
||||
};
|
||||
|
||||
|
||||
struct uwsgi_rpc {
|
||||
char name[0xff];
|
||||
void *func;
|
||||
@@ -1780,6 +1811,8 @@ struct uwsgi_shared {
|
||||
struct uwsgi_gateway gateways[MAX_GATEWAYS];
|
||||
int gateways_cnt;
|
||||
time_t gateways_harakiri[MAX_GATEWAYS];
|
||||
|
||||
int ready;
|
||||
};
|
||||
|
||||
struct uwsgi_core {
|
||||
@@ -1855,6 +1888,8 @@ struct uwsgi_worker {
|
||||
|
||||
uint64_t avg_response_time;
|
||||
|
||||
uint64_t static_offload_threads;
|
||||
|
||||
char name[0xff];
|
||||
};
|
||||
|
||||
@@ -2349,7 +2384,7 @@ int uwsgi_netlink_del(char *);
|
||||
int uwsgi_amqp_consume_queue(int, char *, char *, char *, char *, char *, char *);
|
||||
char *uwsgi_amqp_consume(int, uint64_t *, char **);
|
||||
|
||||
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
int uwsgi_file_serve(struct wsgi_request *, char *, uint16_t, char *, uint16_t, int);
|
||||
inline int uwsgi_starts_with(char *, int, char *, int);
|
||||
|
||||
#ifdef __sun__
|
||||
@@ -2430,6 +2465,7 @@ void uwsgi_string_del_list(struct uwsgi_string_list **, struct uwsgi_string_list
|
||||
|
||||
void uwsgi_init_all_apps(void);
|
||||
void uwsgi_socket_nb(int);
|
||||
void uwsgi_socket_b(int);
|
||||
|
||||
void uwsgi_destroy_request(struct wsgi_request *);
|
||||
|
||||
@@ -2637,7 +2673,12 @@ void uwsgi_opt_set_str(char *, char *, void *);
|
||||
void uwsgi_opt_set_logger(char *, char *, void *);
|
||||
void uwsgi_opt_set_str_spaced(char *, char *, void *);
|
||||
void uwsgi_opt_add_string_list(char *, char *, void *);
|
||||
void uwsgi_opt_add_dyn_dict(char *, char *, void *);
|
||||
#ifdef UWSGI_PCRE
|
||||
void uwsgi_opt_add_regexp_dyn_dict(char *, char *, void *);
|
||||
#endif
|
||||
void uwsgi_opt_set_int(char *, char *, void *);
|
||||
void uwsgi_opt_set_rawint(char *, char *, void *);
|
||||
void uwsgi_opt_set_64bit(char *, char *, void *);
|
||||
void uwsgi_opt_set_megabytes(char *, char *, void *);
|
||||
void uwsgi_opt_set_dyn(char *, char *, void *);
|
||||
@@ -2679,6 +2720,7 @@ void uwsgi_opt_add_daemon(char *, char *, void *);
|
||||
void uwsgi_opt_set_uid(char *, char *, void *);
|
||||
void uwsgi_opt_set_gid(char *, char *, void *);
|
||||
void uwsgi_opt_set_env(char *, char *, void *);
|
||||
void uwsgi_opt_unset_env(char *, char *, void *);
|
||||
void uwsgi_opt_pidfile_signal(char *, char *, void *);
|
||||
void uwsgi_opt_add_app(char *, char *, void *);
|
||||
|
||||
@@ -2715,6 +2757,8 @@ int uwsgi_logic_opt_if_file(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_file(char *, char *);
|
||||
int uwsgi_logic_opt_if_dir(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_dir(char *, char *);
|
||||
int uwsgi_logic_opt_if_reload(char *, char *);
|
||||
int uwsgi_logic_opt_if_not_reload(char *, char *);
|
||||
|
||||
|
||||
#ifdef UWSGI_CAP
|
||||
@@ -2779,6 +2823,9 @@ char *uwsgi_expand_path(char *, int, char *);
|
||||
int uwsgi_try_autoload(char *);
|
||||
|
||||
uint64_t uwsgi_micros(void);
|
||||
int uwsgi_is_file(char *);
|
||||
|
||||
void uwsgi_receive_signal(int, char *, int);
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
int uwsgi_init(int, char **, char **);
|
||||
|
||||
+7
-1
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.2-rc1'
|
||||
uwsgi_version = '1.2'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -306,6 +306,11 @@ class uConf(object):
|
||||
raise
|
||||
except:
|
||||
self.include_path = ['/usr/include', '/usr/local/include']
|
||||
|
||||
additional_include_paths = self.get('additional_include_paths')
|
||||
if additional_include_paths:
|
||||
for ipath in additional_include_paths.split():
|
||||
self.include_path.append(ipath)
|
||||
|
||||
if not mute:
|
||||
print("detected include path: %s" % self.include_path)
|
||||
@@ -387,6 +392,7 @@ class uConf(object):
|
||||
if self.has_include('execinfo.h') or os.path.exists('/usr/local/include/execinfo.h'):
|
||||
if os.path.exists('/usr/local/include/execinfo.h'):
|
||||
self.cflags.append('-I/usr/local/include')
|
||||
self.ldflags.append('-L/usr/local/lib')
|
||||
self.cflags.append('-DUWSGI_HAS_EXECINFO')
|
||||
self.libs.append('-lexecinfo')
|
||||
|
||||
|
||||
Reference in New Issue
Block a user