Compare commits

..
64 Commits
Author SHA1 Message Date
roberto@debian32 b7525475d8 ready for 0.9.8 release 2011-06-05 08:20:23 +02:00
roberto@debian32 f35a36ac02 set a mercy mode for INT/QUIT 2011-06-05 07:38:58 +02:00
roberto@netbsd64 3b53f89a24 netbsd fix 2011-06-05 09:17:38 +02:00
roberto@debian32 764d94e41b support for abstract unix socket prefixed with \0 2011-06-04 08:55:49 +02:00
roberto@indianajones 0292e15497 add /lib to linker on SunOS-derived systems 2011-06-02 19:35:05 +01:00
roberto@debian32 bde4ac7b2f uWSGI 0.9.8-rc4 2011-06-02 18:53:49 +02:00
roberto@debian32 c71fa3abd1 Added tag 0.9.8-rc4 for changeset 0f1f3924ee53 2011-06-02 18:53:38 +02:00
roberto@indianajones d2abdb5d3a fix accept() to receive the correct ip 2011-06-02 18:44:48 +01:00
roberto@indianajones 1392791837 OpenIndiana is now officially supported 2011-06-02 15:15:35 +01:00
roberto@goyle 6f7d9634d5 allows log-date 2011-06-02 12:08:56 +02:00
roberto@goyle 82b95114a8 added welcome.py 2011-06-02 11:38:18 +02:00
roberto@debian32 d90e701acd use int in uwsgi.version_info 2011-06-01 13:02:33 +02:00
roberto@debian32 42993022bb python3 fix 2011-06-01 12:55:20 +02:00
roberto@dj1 29b1e46252 uwsgi.version_info 2011-06-01 05:52:46 -05:00
roberto@sirius 260cea639f better myadmin.py 2011-06-01 10:04:57 +02:00
roberto@sirius 208aea8aca two new management flag for backlog queue 2011-06-01 10:00:17 +02:00
roberto@sirius f164d401d3 another uwsgi_log fix 2011-06-01 09:47:58 +02:00
roberto@dj1 5e1c34a08b really fix uwsgi_log 2011-06-01 02:15:53 -05:00
roberto@debian32 9c7b596a0d fixed uwsgi_log 2011-06-01 08:38:51 +02:00
roberto@debian32 5ff34ac6d0 a couple of admin plugin fixes 2011-06-01 08:12:50 +02:00
roberto@debian32 e304e34929 throw exception on too much big spool requests 2011-06-01 07:11:54 +02:00
roberto@dj1 6d7848248d added --early-emperor option 2011-05-31 08:44:26 -05:00
roberto@sirius dbc0da0586 support for idle mode in single process mode 2011-05-31 14:26:57 +02:00
roberto@debian32 fecdcf9d10 allows sub-emperors (emperors generated by emperors) 2011-05-31 08:56:03 +02:00
roberto@sirius bfd0ab2301 fixed a typo 2011-05-30 19:10:01 +02:00
roberto@sirius 8002777e75 uWSGI 0.9.8-rc3 2011-05-30 19:04:05 +02:00
roberto@debian32 d57d5acb30 --idle mode 2011-05-29 06:52:47 +02:00
roberto@debian32 43e6664dd9 --cheap option 2011-05-28 19:43:29 +02:00
roberto@dj1 d0c6dff83e --add-header option 2011-05-28 05:20:48 -05:00
roberto@dj1 54b40f5978 better cgroup support 2011-05-27 14:23:22 -05:00
roberto@dj1 1c59c03261 unlimited sockets for fastrouter 2011-05-27 08:55:15 -05:00
roberto@dj1 ce23fd38ab better emperor+master mode 2011-05-27 05:11:41 -05:00
roberto@dj1 4818efa7de emperor+amqp fixes 2011-05-27 04:07:07 -05:00
roberto@dj1 ea19e74229 better netlink ns detection 2011-05-27 03:21:21 -05:00
roberto@dj1 fe353de5a8 fixed netlink compilation 2011-05-27 01:58:43 -05:00
roberto@dj1 1d89266f2e unlimited shared sockets 2011-05-27 01:39:01 -05:00
roberto@debian32 61d79394ca --fastrouter-subscription-slot 2011-05-26 05:35:43 +02:00
roberto@debian32 491f2828b5 --no-fd-passing 2011-05-26 05:29:01 +02:00
roberto@nexenta32 431e05d4f4 fixed ifaddrs support 2011-05-26 06:17:46 +02:00
roberto@solarisexpress ae6780a487 remember: do not use the word 'sun' as variable on solaris... 2011-05-26 04:54:55 +00:00
roberto@debian32 5707a70141 added --log-socket 2011-05-25 08:57:13 +02:00
roberto@debian32 e9a7bd7da1 add abstract unix socket 2011-05-23 21:50:04 +02:00
roberto@debian32 91e45daf6c better unix socket support in abstract namespace (Linux only) 2011-05-23 16:10:27 +02:00
roberto@debian32 9f69998075 grunt improvement 2011-05-23 11:43:22 +02:00
roberto@debian32 4f6270976b fixed python3.x spooler 2011-05-22 14:07:01 +02:00
roberto@debian32 328caa43f2 allow --auto-snapshot to take a value 2011-05-22 11:56:58 +02:00
roberto@debian32 368408374a preliminary snapshotting support 2011-05-22 11:43:28 +02:00
roberto@debian32 c3a90db493 uWSGI 0.9.8-rc2 2011-05-21 08:10:03 +02:00
roberto@debian32 5bc0320877 Added tag 0.9.8-rc2 for changeset e91bc724325e 2011-05-21 08:09:49 +02:00
roberto@debian32 622ed620b9 fixed python 3.1 2011-05-21 08:03:22 +02:00
roberto@debian2 1b859413de add mercurial revision to uWSGI version string 2011-05-21 07:43:49 +02:00
roberto@maverick64 95432fd8e3 added --die-on-term 2011-05-19 20:35:47 +02:00
roberto@freebsd64 b3f3c5d7b3 fixed touch reload 2011-05-19 09:33:25 +02:00
roberto@debian32 02cef20462 another fix for wsgi.input 2011-05-19 08:33:11 +02:00
roberto@debian32 3edebe34ae improved upload test 2011-05-18 21:15:41 +02:00
roberto@longshot 28c9b75fb5 wsgi.input fix 2011-05-18 21:10:18 +02:00
roberto@fedora15 a2735e10b7 report number of vassals to systemd 2011-05-17 08:57:50 +02:00
roberto@fedora15 e03d26fd63 report emperor dead status to systemd 2011-05-17 08:36:54 +02:00
roberto@sirius 7c4c346e64 fix systemd on unsupported platform 2011-05-17 08:29:33 +02:00
roberto@fedora15 67b3c0c4a8 systemd integration 2011-05-17 08:26:39 +02:00
roberto@fedora15 dadca785e4 initial systemd support 2011-05-16 17:25:38 +02:00
roberto@debian32 accebe5597 add --log-prefix option 2011-05-16 10:06:47 +02:00
unbit@gambit 792965bedd uWSGI 0.9.8-rc1 2011-05-14 09:57:15 +02:00
unbit@localhost 1bb1bafe0c Added tag 0.9.8-rc1 for changeset d1e57707f631 2011-05-14 09:56:41 +02:00
43 changed files with 1679 additions and 528 deletions
+4
View File
@@ -0,0 +1,4 @@
syntax: glob
*.o
*.pyc
+4
View File
@@ -20,3 +20,7 @@ d9b9b540f7dce8cb05d2e61ca8b4d75f2ea25f62 0.9.7.1
0000000000000000000000000000000000000000 0.9.7.1
486e7760bcbc2191ddb9b4aee6c98dbd5fc4c754 0.9.7.1
a5f13497b39269621f8f1e56e14d2cc141452e79 0.9.7.2
d1e57707f6317f134fea7d12f6588d8690f74f3f 0.9.8-rc1
e91bc724325e14c13b8f548c0b6a315c48a1c32a 0.9.8-rc2
4fb424d52f226a0a087fea89709f5eb540e03f25 0.9.8-rc3
0f1f3924ee5309a9990d9af1ffc68846e3dfb31b 0.9.8-rc4
+74
View File
@@ -1,3 +1,77 @@
*** may 2011 ***
* 0.9.8-rc4 [20110602]
- fixed REMOTE_ADDR when --protocol=http
- official support for OpenIndiana
- added a welcome.py test script
- new api attribute uwsgi.version_info
- improved the admin plugin
- two new management flag for backlog queue monitoring
- fixed uwsgi_log for bigger loglines
- new option --early-emperor to allows out-of-jail emperors
- emperor can now spawn other emperors (sub-emperors)
- fixed idle mode in single-process
- fixed solaris iovec
* 0.9.8-rc3 [20110530]
- snapshotting support
- fixed python 3.x spooler
- improvements for grunt processes
- better abstract unix socket
- --log-socket allows logging to generic DGRAM sockets
- a bunch of solaris fixes
- new option --no-fd-passing for fastrouter
- --fastrouter-subscription-slot to set the number of slot in subscription server
- unlimited shared sockets
- fixed netlink compilation
- auto-reconnect on emperor+amqp server disconnection
- various emperor fixes
- unlimited fastrouter sockets
- better cgroup support
- --add-header option allow adding of custom HTTP response headers
- cheap and idle operational modes
* 0.9.8-rc2 [20110521]
- new option --die-on-term
- fixed touch reload
- a couple of optimizations for wsgi.input
- systemd integration
* 0.9.8-rc1 [20110514]
- massive code cleanup and refactoring
- added vassals loyalty concept
- fixed virtualhosting with dynamic virtualenv
- fixed reloading on grand-central-dispatch-enabled OSX
- improved PSGI support with uGreen and async support
- improved Rack support with complete fiber+async in ruby 1.9
- support for JSON config files
- native multi-protocol support (added fastcgi and http)
- Mongrel2 support
- support for templates in vassals
- various threading fixes
- gcc-4.6 support
- support for logging via zeromq
- support for configuration passed via pipe/stdin
- pythonpath entries are now unlimited
- socket entries are unlimited
- pythonpath can be a glob
- lazy mode added
- new language-independent profiling subsystem
- support for configuration stored in a sqlite3 db
- allow workers to survive to syslogd death (when --log-syslog is used)
- fix traceback in Python 3.x
- support for uwsgi signals in threads
- plugin autoloading
- graceful reloading for threads
- new wsgi.input object
- support for alternative allocators (tcmalloc and jemalloc)
*** april 2011 ***
* 0.9.7.2 [20110406]
+2
View File
@@ -318,7 +318,9 @@ void *async_loop(void *arg1) {
// parsing complete
if (!proto_parser_status) {
// remove fd from event poll and fd proto table
#ifndef UWSGI_EVENT_USE_PORT
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
#endif
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
// put request in the runqueue
runqueue_push(uwsgi.wsgi_req);
+1
View File
@@ -25,6 +25,7 @@ yaml_implementation = auto
malloc_implementation = libc
plugins =
bin_name = uwsgi
append_version =
plugin_dir = .
embedded_plugins = python, ping, cache, nagios, rpc, fastrouter, http, ugreen
+26 -3
View File
@@ -7,6 +7,11 @@ extern char **environ;
int emperor_queue;
static void royal_death(int signum) {
uwsgi_notify("The Emperor is buried.");
exit(0);
}
struct uwsgi_instance {
struct uwsgi_instance *ui_prev;
struct uwsgi_instance *ui_next;
@@ -194,6 +199,7 @@ void emperor_add(char *name, time_t born, char *config, uint32_t config_size) {
else {
unsetenv("UWSGI_RELOADS");
unsetenv("NOTIFY_SOCKET");
uef = uwsgi_num2str(n_ui->pipe[1]);
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
@@ -309,8 +315,11 @@ void emperor_loop() {
void *events;
int nevents;
int interesting_fd;
char notification_message[64];
signal(SIGPIPE, SIG_IGN);
uwsgi_unix_signal(SIGINT, royal_death);
uwsgi_unix_signal(SIGTERM, royal_death);
memset(&ui_base, 0, sizeof(struct uwsgi_instance));
@@ -319,7 +328,12 @@ void emperor_loop() {
events = event_queue_alloc(64);
uwsgi_log("*** starting uWSGI Emperor ***\n");
if (uwsgi.has_emperor) {
uwsgi_log("*** starting uWSGI sub-Emperor ***\n");
}
else {
uwsgi_log("*** starting uWSGI Emperor ***\n");
}
amqp_port = strchr(uwsgi.emperor_dir, ':');
@@ -347,7 +361,7 @@ reconnect:
event_queue_add_fd_read(emperor_queue, amqp_fd);
}
else {
if (!glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
if (!glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
if (g.gl_pathc == 1 && g.gl_pathv[0][strlen(g.gl_pathv[0]) - 1] == '/') {
simple_mode = 1;
if (chdir(uwsgi.emperor_dir)) {
@@ -388,6 +402,7 @@ reconnect:
if (!config) {
uwsgi_log("problem with RabbitMQ server, trying reconnection...\n");
event_queue_del_fd(emperor_queue, amqp_fd, event_queue_read());
close(amqp_fd);
amqp_fd = -1;
goto reconnect;
@@ -478,6 +493,7 @@ reconnect:
}
else {
uwsgi_log("unrecognized event on fd %d\n", interesting_fd);
event_queue_del_fd(emperor_queue, interesting_fd, event_queue_read());
close(interesting_fd);
}
}
@@ -520,7 +536,7 @@ reconnect:
closedir(dir);
}
else {
if (glob(uwsgi.emperor_dir, GLOB_MARK, NULL, &g)) {
if (glob(uwsgi.emperor_dir, GLOB_MARK|GLOB_NOCHECK, NULL, &g)) {
uwsgi_error("glob()");
continue;
}
@@ -569,6 +585,12 @@ reconnect:
has_children++;
}
if (uwsgi.notify) {
if (snprintf(notification_message, 64, "The Emperor is governing %d vassals", has_children) >= 34) {
uwsgi_notify(notification_message);
}
}
if (has_children) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
@@ -620,6 +642,7 @@ reconnect:
}
}
}
}
+1 -1
View File
@@ -4,7 +4,7 @@
#include <linux/rtnetlink.h>
#include <net/if.h>
#ifdef IFLA_NET_NS_PID
#ifdef CLONE_NEWNET
#define NLMSG_TAIL(nmsg) \
((struct rtattr *) (((void *) (nmsg)) + NLMSG_ALIGN((nmsg)->nlmsg_len)))
+3 -10
View File
@@ -68,11 +68,7 @@ void *simple_loop(void *arg1) {
// initialize the main event queue to monitor sockets
uwsgi.main_queue = event_queue_init();
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
event_queue_add_fd_read(uwsgi.main_queue, uwsgi_sock->fd);
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_add_sockets_to_queue(uwsgi.main_queue);
if (uwsgi.signal_socket > -1) {
event_queue_add_fd_read(uwsgi.main_queue, uwsgi.signal_socket);
@@ -94,9 +90,7 @@ void *simple_loop(void *arg1) {
uwsgi_close_request(wsgi_req);
}
pthread_exit(NULL);
//never here
// end of the loop
return NULL;
}
@@ -202,8 +196,7 @@ void *zeromq_loop(void *arg1) {
}
pthread_exit(NULL);
//never here
// end of the loop
return NULL;
}
#endif
+157 -91
View File
@@ -2,6 +2,17 @@
extern struct uwsgi_server uwsgi;
void uwsgi_restore_auto_snapshot(int signum) {
if (uwsgi.workers[1].snapshot > 0) {
uwsgi.restore_snapshot = 1;
}
else {
uwsgi_log("[WARNING] no snapshot available\n");
}
}
void expire_rb_timeouts(struct rb_root *root) {
time_t current = time(NULL);
@@ -85,8 +96,11 @@ void get_linux_tcp_info(int fd) {
if (!uwsgi.shared->ti.tcpi_sacked) {
return;
}
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_STATUS] = uwsgi.shared->ti.tcpi_unacked;
if (uwsgi.shared->ti.tcpi_unacked >= uwsgi.shared->ti.tcpi_sacked) {
uwsgi_log_verbose("*** uWSGI listen queue of socket %d full !!! (%d/%d) ***\n", fd, uwsgi.shared->ti.tcpi_unacked, uwsgi.shared->ti.tcpi_sacked);
uwsgi.shared->options[UWSGI_OPTION_BACKLOG_ERRORS]++;
}
}
}
@@ -121,16 +135,14 @@ void manage_cluster_announce(char *key, uint16_t keylen, char *val, uint16_t val
void master_loop(char **argv, char **environ) {
uint64_t master_cycles = 0;
uint64_t tmp_counter;
char log_buf[4096];
time_t current_time = time(NULL);
struct timeval last_respawn;
int last_respawn_rate = 0;
pid_t pid;
int pid_found = 0;
pid_t diedpid;
@@ -143,6 +155,9 @@ void master_loop(char **argv, char **environ) {
uint8_t uwsgi_signal;
time_t last_request_timecheck = 0;
uint64_t last_request_count = 0;
#ifdef UWSGI_UDP
struct sockaddr_in udp_client;
socklen_t udp_len;
@@ -174,12 +189,22 @@ void master_loop(char **argv, char **environ) {
struct rb_root *rb_timers = uwsgi_init_rb_timer();
struct tm *uwsgi_cron_delta;
uwsgi.current_time = time(NULL);
uwsgi_unix_signal(SIGHUP, grace_them_all);
uwsgi_unix_signal(SIGTERM, reap_them_all);
if (uwsgi.die_on_term) {
uwsgi_unix_signal(SIGTERM, kill_them_all);
uwsgi_unix_signal(SIGQUIT, reap_them_all);
}
else {
uwsgi_unix_signal(SIGTERM, reap_them_all);
uwsgi_unix_signal(SIGQUIT, kill_them_all);
}
uwsgi_unix_signal(SIGINT, kill_them_all);
uwsgi_unix_signal(SIGQUIT, kill_them_all);
uwsgi_unix_signal(SIGUSR1, stats);
if (uwsgi.auto_snapshot) {
uwsgi_unix_signal(SIGURG, uwsgi_restore_auto_snapshot);
}
uwsgi.master_queue = event_queue_init();
@@ -214,6 +239,12 @@ void master_loop(char **argv, char **environ) {
event_queue_add_fd_read(uwsgi.master_queue, udp_fd);
}
}
if (uwsgi.cheap) {
uwsgi_add_sockets_to_queue(uwsgi.master_queue);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
}
#ifdef UWSGI_MULTICAST
if (uwsgi.cluster) {
@@ -376,29 +407,46 @@ void master_loop(char **argv, char **environ) {
}
}
}
if (ready_to_die >= uwsgi.numproc && uwsgi.to_hell) {
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
kill(uwsgi.shared->spooler_pid, SIGKILL);
uwsgi_log( "killed the spooler with pid %d\n", uwsgi.shared->spooler_pid);
if (uwsgi.respawn_workers) {
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi_respawn_worker(i)) return;
}
#endif
uwsgi.respawn_workers = 0;
}
if (uwsgi.restore_snapshot) {
uwsgi_log("[snapshot] restoring workers...\n");
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid == 0) continue;
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
uwsgi.workers[i].pid = 0;
uwsgi.workers[i].snapshot = 0;
}
else {
uwsgi.workers[i].pid = uwsgi.workers[i].snapshot;
uwsgi.workers[i].snapshot = 0;
kill(uwsgi.workers[i].pid, SIGURG);
uwsgi_log( "Restored uWSGI worker %d (pid: %d)\n", i, (int) uwsgi.workers[i].pid);
}
}
uwsgi.restore_snapshot = 0;
continue;
}
if ((uwsgi.cheap || ready_to_die >= uwsgi.numproc) && uwsgi.to_hell) {
// call a series of waitpid to ensure all processes (gateways and daemons) are dead
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt);i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
}
// TODO kill all the gateways
uwsgi_log( "goodbye to uWSGI.\n");
exit(0);
}
if (ready_to_reload >= uwsgi.numproc && uwsgi.to_heaven) {
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
kill(uwsgi.shared->spooler_pid, SIGKILL);
uwsgi_log( "wait4() the spooler with pid %d...", uwsgi.shared->spooler_pid);
diedpid = waitpid(uwsgi.shared->spooler_pid, &waitpid_status, 0);
uwsgi_log( "done.");
}
#endif
if ( (uwsgi.cheap || ready_to_reload >= uwsgi.numproc) && uwsgi.to_heaven) {
// call a series of waitpid to ensure all processes (gateways and daemons) are dead
for(i=0;i<(uwsgi.gateways_cnt+ushared->daemons_cnt);i++) {
diedpid = waitpid(WAIT_ANY, &waitpid_status, WNOHANG);
@@ -454,14 +502,17 @@ void master_loop(char **argv, char **environ) {
exit(1);
}
if (uwsgi.numproc > 0 || uwsgi.gateways_cnt > 0 || ushared->daemons_cnt > 0) {
master_has_children = 1;
}
if (!uwsgi.cheap) {
if (uwsgi.numproc > 0 || uwsgi.gateways_cnt > 0 || ushared->daemons_cnt > 0) {
master_has_children = 1;
}
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
master_has_children = 1;
}
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
master_has_children = 1;
}
#endif
}
if (!master_has_children) {
diedpid = 0;
@@ -549,8 +600,8 @@ void master_loop(char **argv, char **environ) {
// check uwsgi-cron table
if (ushared->cron_cnt) {
current_time = time(NULL);
uwsgi_cron_delta = localtime( &current_time );
uwsgi.current_time = time(NULL);
uwsgi_cron_delta = localtime( &uwsgi.current_time );
if (uwsgi_cron_delta) {
@@ -601,9 +652,9 @@ void master_loop(char **argv, char **environ) {
// date match, signal it ?
if (current_time - ucron->last_job > 60) {
if (uwsgi.current_time - ucron->last_job > 60) {
uwsgi_route_signal(ucron->sig);
ucron->last_job = current_time;
ucron->last_job = uwsgi.current_time;
}
}
@@ -634,6 +685,9 @@ void master_loop(char **argv, char **environ) {
}
}
#endif
else if (uwsgi.log_socket) {
sendto(uwsgi.log_socket_fd, log_buf, rlen, 0, &uwsgi.log_socket_addr->sa, uwsgi.log_socket_size);
}
// TODO allow uwsgi.logger = func
}
}
@@ -664,6 +718,25 @@ void master_loop(char **argv, char **environ) {
}
}
}
if (uwsgi.cheap) {
int found = 0 ;
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
found = 1;
uwsgi.cheap = 0;
uwsgi_del_sockets_from_queue(uwsgi.master_queue);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi_respawn_worker(i)) return;
}
break;
}
uwsgi_sock = uwsgi_sock->next;
}
if (found) continue;
}
#ifdef UWSGI_SNMP
if (uwsgi.snmp_addr && interesting_fd == snmp_fd) {
udp_len = sizeof(udp_client);
@@ -826,7 +899,7 @@ void master_loop(char **argv, char **environ) {
}
}
current_time = time(NULL);
uwsgi.current_time = time(NULL);
// checking logsize
if (uwsgi.logfile) {
uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
@@ -844,25 +917,49 @@ void master_loop(char **argv, char **environ) {
}
master_cycles++;
uwsgi.master_cycles++;
// recalculate requests counter on race conditions risky configurations
// a bit of inaccuracy is better than locking;)
if (uwsgi.numproc > 1) {
tmp_counter = 0;
for(i=1;i<uwsgi.numproc+1;i++) {
for(i=1;i<uwsgi.numproc+1;i++)
tmp_counter += uwsgi.workers[i].requests;
}
uwsgi.workers[0].requests = tmp_counter;
}
if (uwsgi.idle > 0 && !uwsgi.cheap) {
uwsgi.current_time = time(NULL);
if (!last_request_timecheck) last_request_timecheck = uwsgi.current_time;
if (last_request_count != uwsgi.workers[0].requests) {
last_request_timecheck = uwsgi.current_time;
last_request_count = uwsgi.workers[0].requests;
}
else if (uwsgi.current_time - last_request_timecheck > uwsgi.idle) {
uwsgi_log("workers have been inactive for more than %d seconds\n", uwsgi.idle);
for(i=1;i<=uwsgi.numproc;i++) {
if (uwsgi.workers[i].pid == 0) continue;
kill(uwsgi.workers[i].pid, SIGKILL);
if (waitpid(uwsgi.workers[i].pid, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
}
master_has_children = 0;
uwsgi.cheap = 1;
uwsgi_add_sockets_to_queue(uwsgi.master_queue);
uwsgi_log("cheap mode enabled: waiting for socket connection...\n");
last_request_timecheck = 0;
continue;
}
}
// remove expired cache items TODO use rb_tree timeouts
if (uwsgi.cache_max_items > 0) {
for(i=0;i< (int)uwsgi.cache_max_items;i++) {
uwsgi_wlock(uwsgi.cache_lock);
if (uwsgi.cache_items[i].expires) {
if (uwsgi.cache_items[i].expires < (uint64_t) current_time) {
if (uwsgi.cache_items[i].expires < (uint64_t) uwsgi.current_time) {
uwsgi_cache_del(uwsgi.cache_items[i].key, uwsgi.cache_items[i].keysize);
}
}
@@ -888,7 +985,7 @@ void master_loop(char **argv, char **environ) {
for (i = 1; i <= uwsgi.numproc; i++) {
/* first check for harakiri */
if (uwsgi.workers[i].harakiri > 0) {
if (uwsgi.workers[i].harakiri < (time_t) current_time) {
if (uwsgi.workers[i].harakiri < (time_t) uwsgi.current_time) {
/* first try to invoke the harakiri() custom handler */
/* TODO */
/* then brutally kill the worker */
@@ -942,37 +1039,15 @@ void master_loop(char **argv, char **environ) {
#ifdef UWSGI_UDP
// check for cluster nodes
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_STATIC && ucn->status == UWSGI_NODE_FAILED) {
// should i retry ?
if (master_cycles % ucn->errors == 0) {
if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
ucn->status = UWSGI_NODE_OK;
uwsgi_log( "re-enabled cluster node %d/%s\n", i, ucn->name);
}
else {
ucn->errors++;
}
}
}
else if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_DYNAMIC) {
// if the last_seen attr is higher than 30 secs ago, mark the node as dead
if ( (current_time - ucn->last_seen) > 30) {
uwsgi_log_verbose("no presence announce in the last 30 seconds by node %s, i assume it is dead.\n", ucn->name);
ucn->name[0] = 0 ;
}
}
}
master_check_cluster_nodes();
// reannounce myself every 10 cycles
if (uwsgi.cluster && uwsgi.cluster_fd >= 0 && !uwsgi.cluster_nodes && (master_cycles % 10) == 0) {
if (uwsgi.cluster && uwsgi.cluster_fd >= 0 && !uwsgi.cluster_nodes && (uwsgi.master_cycles % 10) == 0) {
uwsgi_cluster_add_me();
}
// resubscribe every 10 cycles
if (uwsgi.subscriptions_cnt > 0 && ((master_cycles % 10) == 0 || master_cycles == 1)) {
if (uwsgi.subscriptions_cnt > 0 && ((uwsgi.master_cycles % 10) == 0 || uwsgi.master_cycles == 1)) {
for(i=0;i<uwsgi.subscriptions_cnt;i++) {
uwsgi_subscribe(uwsgi.subscriptions[i]);
}
@@ -980,13 +1055,13 @@ void master_loop(char **argv, char **environ) {
#endif
if (uwsgi.cache_store && uwsgi.cache_filesize && uwsgi.cache_store_sync && ((master_cycles % uwsgi.cache_store_sync) == 0)) {
if (uwsgi.cache_store && uwsgi.cache_filesize && uwsgi.cache_store_sync && ((uwsgi.master_cycles % uwsgi.cache_store_sync) == 0)) {
if (msync(uwsgi.cache_items, uwsgi.cache_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
}
if (uwsgi.queue_store && uwsgi.queue_filesize && uwsgi.queue_store_sync && ((master_cycles % uwsgi.queue_store_sync) == 0)) {
if (uwsgi.queue_store && uwsgi.queue_filesize && uwsgi.queue_store_sync && ((uwsgi.master_cycles % uwsgi.queue_store_sync) == 0)) {
if (msync(uwsgi.queue, uwsgi.queue_filesize, MS_ASYNC)) {
uwsgi_error("msync()");
}
@@ -1002,7 +1077,7 @@ void master_loop(char **argv, char **environ) {
}
else {
if (tr_st.st_mtime > uwsgi.last_touch_reload_mtime) {
uwsgi_log("*** %s has been touched... grace them all !!! ***\n");
uwsgi_log("*** %s has been touched... grace them all !!! ***\n", uwsgi.touch_reload);
grace_them_all(0);
}
}
@@ -1015,6 +1090,9 @@ void master_loop(char **argv, char **environ) {
continue;
}
// reload gateways and daemons only on normal workflow
if (!uwsgi.to_heaven && !uwsgi.to_hell) {
#ifdef UWSGI_SPOOLER
/* reload the spooler */
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
@@ -1026,8 +1104,6 @@ void master_loop(char **argv, char **environ) {
}
#endif
// reload gateways and daemons only on normal workflow
if (!uwsgi.to_heaven && !uwsgi.to_hell) {
/* reload the gateways */
// TODO reload_gateway(diedpid);
pid_found = 0;
@@ -1053,6 +1129,7 @@ void master_loop(char **argv, char **environ) {
}
if (pid_found) continue;
}
/* What happens here ?
@@ -1101,9 +1178,16 @@ void master_loop(char **argv, char **environ) {
}
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");
/* TODO, user configurable fork throttler */
sleep(2);
last_respawn_rate++;
if (last_respawn_rate > uwsgi.numproc) {
uwsgi_log( "worker respawning too fast !!! i have to sleep a bit...\n");
/* TODO, user configurable fork throttler */
sleep(2);
last_respawn_rate = 0;
}
}
else {
last_respawn_rate = 0;
}
gettimeofday(&last_respawn, NULL);
uwsgi.respawn_delta = last_respawn.tv_sec;
@@ -1115,27 +1199,9 @@ void master_loop(char **argv, char **environ) {
continue;
}
*/
pid = fork();
if (pid == 0) {
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
uwsgi.mypid = getpid();
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].requests = 0;
uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = current_time;
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
break;
}
else if (pid < 1) {
uwsgi_error("fork()");
}
else {
uwsgi_log( "Respawned uWSGI worker %d (new pid: %d)\n", uwsgi.mywid, (int) pid);
}
if (uwsgi_respawn_worker(uwsgi.mywid)) return;
}
}
}
+69
View File
@@ -0,0 +1,69 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void master_check_cluster_nodes() {
int i;
for (i = 0; i < MAX_CLUSTER_NODES; i++) {
struct uwsgi_cluster_node *ucn = &uwsgi.shared->nodes[i];
if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_STATIC && ucn->status == UWSGI_NODE_FAILED) {
// should i retry ?
if (uwsgi.master_cycles % ucn->errors == 0) {
if (!uwsgi_ping_node(i, uwsgi.wsgi_req)) {
ucn->status = UWSGI_NODE_OK;
uwsgi_log( "re-enabled cluster node %d/%s\n", i, ucn->name);
}
else {
ucn->errors++;
}
}
}
else if (ucn->name[0] != 0 && ucn->type == CLUSTER_NODE_DYNAMIC) {
// if the last_seen attr is higher than 30 secs ago, mark the node as dead
if ( (uwsgi.current_time - ucn->last_seen) > 30) {
uwsgi_log_verbose("no presence announce in the last 30 seconds by node %s, i assume it is dead.\n", ucn->name);
ucn->name[0] = 0 ;
}
}
}
}
int uwsgi_respawn_worker(int wid) {
int respawns = uwsgi.workers[wid].respawn_count;
pid_t pid = fork();
if (pid == 0) {
uwsgi.mywid = wid;
// fix the communication pipe
close(uwsgi.shared->worker_signal_pipe[0]);
uwsgi.mypid = getpid();
uwsgi.workers[uwsgi.mywid].pid = uwsgi.mypid;
uwsgi.workers[uwsgi.mywid].id = uwsgi.mywid;
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[uwsgi.mywid].requests = 0;
uwsgi.workers[uwsgi.mywid].failed_requests = 0;
uwsgi.workers[uwsgi.mywid].respawn_count++;
uwsgi.workers[uwsgi.mywid].last_spawn = uwsgi.current_time;
uwsgi.workers[uwsgi.mywid].manage_next_request = 1;
return 1;
}
else if (pid < 1) {
uwsgi_error("fork()");
}
else {
if (respawns > 0) {
uwsgi_log( "Respawned uWSGI worker %d (new pid: %d)\n", uwsgi.mywid, (int) pid);
}
else {
uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", wid, pid, uwsgi.cores);
}
}
return 0;
}
+11 -1
View File
@@ -2,6 +2,16 @@ import uwsgi
import struct
import sys
print sys.argv
if len(sys.argv) == 3:
chunks = uwsgi.send_message(sys.argv[1], 10, int(sys.argv[2]), '')
print uwsgi.send_uwsgi_message(sys.argv[1], int(sys.argv[2]), 10, int(sys.argv[3]), struct.pack("i", int(sys.argv[4])))
pkt = ''
for chunk in chunks:
pkt += chunk
print "%d = %d" % (int(sys.argv[2]), struct.unpack("I", pkt)[0])
elif len(sys.argv) == 4:
uwsgi.send_message(sys.argv[1], 10, int(sys.argv[2]), struct.pack("I", int(sys.argv[3])))
+72
View File
@@ -0,0 +1,72 @@
#include "uwsgi.h"
extern struct uwsgi_server uwsgi;
void uwsgi_systemd_notify(char *message) {
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
struct iovec *iovec = msghdr->msg_iov;
iovec[0].iov_base = "STATUS=";
iovec[0].iov_len = 7;
iovec[1].iov_base = message;
iovec[1].iov_len = strlen(message);
iovec[2].iov_base = "\n";
iovec[2].iov_len = 1;
msghdr->msg_iovlen = 3;
sendmsg(uwsgi.notification_fd, msghdr, 0);
}
void uwsgi_systemd_notify_ready(void) {
struct msghdr *msghdr = (struct msghdr *) uwsgi.notification_object;
struct iovec *iovec = msghdr->msg_iov;
iovec[0].iov_base = "STATUS=uWSGI is ready\nREADY=1\n";
iovec[0].iov_len = 30;
msghdr->msg_iovlen = 1;
sendmsg(uwsgi.notification_fd, msghdr, 0);
}
void uwsgi_systemd_init(char *systemd_socket) {
struct sockaddr_un *sd_sun;
struct msghdr *msghdr;
uwsgi.notification_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (uwsgi.notification_fd < 0) {
uwsgi_error("socket()");
return;
}
sd_sun = uwsgi_malloc(sizeof(struct sockaddr_un));
memset(sd_sun, 0, sizeof(struct sockaddr_un));
sd_sun->sun_family = AF_UNIX;
strncpy(sd_sun->sun_path, systemd_socket, sizeof(sd_sun->sun_path));
if (sd_sun->sun_path[0] == '@') sd_sun->sun_path[0] = 0;
msghdr = uwsgi_malloc(sizeof(struct msghdr));
memset(msghdr, 0, sizeof(struct msghdr));
msghdr->msg_iov = uwsgi_malloc(sizeof(struct iovec)*3);
memset(msghdr->msg_iov, 0, sizeof(struct iovec)*3);
msghdr->msg_name = sd_sun;
msghdr->msg_namelen = sizeof(struct sockaddr_un);
uwsgi.notification_object = msghdr;
uwsgi.notify = uwsgi_systemd_notify;
uwsgi.notify_ready = uwsgi_systemd_notify_ready;
}
+47 -17
View File
@@ -1,28 +1,58 @@
#include "../../uwsgi.h"
extern struct uwsgi_server uwsgi;
/* uwsgi ADMIN|10 */
int uwsgi_request_admin(struct wsgi_request *wsgi_req) {
uint32_t opt_value = 0;
int i;
ssize_t len;
if (wsgi_req->uh.pktsize >= 4) {
if (wsgi_req->uh.pktsize != 0 && wsgi_req->uh.pktsize != 4)
return UWSGI_OK;
// write request
if (wsgi_req->uh.pktsize == 4) {
memcpy(&opt_value, wsgi_req->buffer, 4);
// TODO: check endianess ?
}
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
// ACK
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
i = write(wsgi_req->poll.fd, wsgi_req, 4);
if (i != 4) {
uwsgi_error("write()");
}
uwsgi_log( "setting internal option %d to %d\n", wsgi_req->uh.modifier2, opt_value);
uwsgi.shared->options[wsgi_req->uh.modifier2] = opt_value;
// ACK
wsgi_req->uh.modifier1 = 255;
wsgi_req->uh.pktsize = 0;
wsgi_req->uh.modifier2 = 1;
len = write(wsgi_req->poll.fd, wsgi_req, 4);
if (len != 4) {
uwsgi_error("write()");
}
}
// get request
else {
uwsgi_log( "internal option %d = %d\n", wsgi_req->uh.modifier2, uwsgi.shared->options[wsgi_req->uh.modifier2]);
wsgi_req->uh.modifier1 = 10;
wsgi_req->uh.pktsize = 4;
len = write(wsgi_req->poll.fd, wsgi_req, 4);
if (len != 4) {
uwsgi_error("write()");
return UWSGI_OK;
}
len = write(wsgi_req->poll.fd, (char *) &uwsgi.shared->options[wsgi_req->uh.modifier2], 4);
if (len != 4) {
uwsgi_error("write()");
}
}
return UWSGI_OK;
}
struct uwsgi_plugin admin_plugin = {
.name = "admin",
.modifier1 = 10,
.request = uwsgi_request_admin,
};
+7
View File
@@ -0,0 +1,7 @@
NAME='admin'
CFLAGS = []
LDFLAGS = []
LIBS = []
GCC_LIST = ['admin_plugin']
+108 -49
View File
@@ -18,6 +18,7 @@
#define LONG_ARGS_FASTROUTER_USE_BASE 150004
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER 150005
#define LONG_ARGS_FASTROUTER_TIMEOUT 150006
#define LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT 150007
#define FASTROUTER_STATUS_FREE 0
#define FASTROUTER_STATUS_CONNECTING 1
@@ -28,25 +29,62 @@
#define add_timeout(x) uwsgi_add_rb_timer(ufr.timeouts, time(NULL)+ufr.socket_timeout, x)
#define del_timeout(x) rb_erase(&x->timeout->rbt, ufr.timeouts); free(x->timeout);
struct uwsgi_fastrouter_socket {
char *name;
int fd;
struct uwsgi_fastrouter_socket *next;
};
struct uwsgi_fastrouter {
char *socket_name;
int use_cache;
int nevents;
char *pattern;
int pattern_len;
struct uwsgi_fastrouter_socket *sockets;
char *base;
int base_len;
int use_cache;
int nevents;
char *subscription_server;
struct uwsgi_dict *subscription_dict;
int subscription_slot;
int socket_timeout;
char *pattern;
int pattern_len;
struct rb_root *timeouts;
char *base;
int base_len;
char *subscription_server;
struct uwsgi_dict *subscription_dict;
int socket_timeout;
struct rb_root *timeouts;
} ufr;
static struct uwsgi_fastrouter_socket *uwsgi_fastrouter_new_socket(char *name) {
struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
ufr.sockets = uwsgi_malloc(sizeof(struct uwsgi_fastrouter_socket));
uwsgi_sock = ufr.sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_fastrouter_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_fastrouter_socket));
uwsgi_sock->name = name;
return uwsgi_sock;
}
struct option fastrouter_options[] = {
{"fastrouter", required_argument, 0, LONG_ARGS_FASTROUTER},
{"fastrouter-use-cache", no_argument, &ufr.use_cache, 1},
@@ -54,6 +92,7 @@ struct option fastrouter_options[] = {
{"fastrouter-use-base", required_argument, 0, LONG_ARGS_FASTROUTER_USE_BASE},
{"fastrouter-events", required_argument, 0, LONG_ARGS_FASTROUTER_EVENTS},
{"fastrouter-subscription-server", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER},
{"fastrouter-subscription-slot", required_argument, 0, LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT},
{"fastrouter-timeout", required_argument, 0, LONG_ARGS_FASTROUTER_TIMEOUT},
{0, 0, 0, 0},
};
@@ -163,7 +202,6 @@ struct fastrouter_session *alloc_fr_session() {
void fastrouter_loop() {
int fr_queue;
int fr_server = -1;
int nevents;
int interesting_fd;
int new_connection;
@@ -210,37 +248,43 @@ void fastrouter_loop() {
fr_table[i] = NULL;
}
if (ufr.socket_name[0] == '=') {
int shared_socket = atoi(ufr.socket_name+1);
if (shared_socket >= 0 && shared_socket < uwsgi.shared_sockets_cnt) {
if (uwsgi.shared_sockets[shared_socket].name) {
fr_server = uwsgi.shared_sockets[shared_socket].fd;
}
else {
uwsgi_log("unable to use shared socket %d\n", shared_socket);
fr_queue = event_queue_init();
struct uwsgi_fastrouter_socket *ufr_sock = ufr.sockets;
while(ufr_sock) {
if (ufr_sock->name[0] == '=') {
int shared_socket = atoi(ufr_sock->name+1);
if (shared_socket >= 0) {
ufr_sock->fd = uwsgi_get_shared_socket_fd_by_num(shared_socket);
if (ufr_sock->fd == -1) {
uwsgi_log("unable to use shared socket %d\n", shared_socket);
}
}
}
}
else {
tcp_port = strchr(ufr.socket_name, ':');
if (tcp_port) {
fr_server = bind_to_tcp(ufr.socket_name, uwsgi.listen_queue, tcp_port);
}
else {
fr_server = bind_to_unix(ufr.socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
tcp_port = strchr(ufr_sock->name, ':');
if (tcp_port) {
ufr_sock->fd = bind_to_tcp(ufr_sock->name, uwsgi.listen_queue, tcp_port);
}
else {
ufr_sock->fd = bind_to_unix(ufr_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
}
}
event_queue_add_fd_read(fr_queue, ufr_sock->fd);
ufr_sock = ufr_sock->next;
}
fr_queue = event_queue_init();
events = event_queue_alloc(ufr.nevents);
event_queue_add_fd_read(fr_queue, fr_server);
if (ufr.subscription_server) {
ufr_subserver = bind_to_udp(ufr.subscription_server, 0, 0);
event_queue_add_fd_read(fr_queue, ufr_subserver);
ufr.subscription_dict = uwsgi_dict_create(30, 0);
if (!ufr.subscription_slot) ufr.subscription_slot = 30;
ufr.subscription_dict = uwsgi_dict_create(ufr.subscription_slot, 0);
}
if (ufr.pattern) {
@@ -276,27 +320,39 @@ void fastrouter_loop() {
interesting_fd = event_queue_interesting_fd(events, i);
if (interesting_fd == fr_server) {
new_connection = accept(fr_server, (struct sockaddr *) &fr_addr, &fr_addr_len);
if (new_connection < 0) {
continue;
}
int taken = 0;
struct uwsgi_fastrouter_socket *uwsgi_sock = ufr.sockets;
while(uwsgi_sock) {
if (interesting_fd == uwsgi_sock->fd) {
new_connection = accept(interesting_fd, (struct sockaddr *) &fr_addr, &fr_addr_len);
if (new_connection < 0) {
continue;
}
fr_table[new_connection] = alloc_fr_session();
fr_table[new_connection]->fd = new_connection;
fr_table[new_connection]->instance_fd = -1;
fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
fr_table[new_connection]->h_pos = 0;
fr_table[new_connection]->pos = 0;
fr_table[new_connection]->instance_failed = 0;
fr_table[new_connection]->instance_address_len = 0;
fr_table[new_connection] = alloc_fr_session();
fr_table[new_connection]->fd = new_connection;
fr_table[new_connection]->instance_fd = -1;
fr_table[new_connection]->status = FASTROUTER_STATUS_RECV_HDR;
fr_table[new_connection]->h_pos = 0;
fr_table[new_connection]->pos = 0;
fr_table[new_connection]->instance_failed = 0;
fr_table[new_connection]->instance_address_len = 0;
fr_table[new_connection]->timeout = add_timeout(fr_table[new_connection]);
fr_table[new_connection]->timeout = add_timeout(fr_table[new_connection]);
event_queue_add_fd_read(fr_queue, new_connection);
event_queue_add_fd_read(fr_queue, new_connection);
taken = 1;
break;
}
uwsgi_sock = uwsgi_sock->next;
}
else if (interesting_fd == ufr_subserver) {
if (taken) {
continue;
}
if (interesting_fd == ufr_subserver) {
len = recv(ufr_subserver, bbuf, 4096, 0);
#ifdef UWSGI_EVENT_USE_PORT
event_queue_add_fd_read(fr_queue, ufr_subserver);
@@ -437,7 +493,7 @@ void fastrouter_loop() {
iov[1].iov_len = fr_session->uh.pktsize;
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (fr_session->pass_fd) {
if (fr_session->pass_fd && !uwsgi.no_fd_passing) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = iov;
@@ -532,7 +588,7 @@ void fastrouter_loop() {
int fastrouter_init() {
if (ufr.socket_name) {
if (ufr.sockets) {
if (ufr.use_cache && !uwsgi.cache_max_items) {
uwsgi_log("you need to create a uwsgi cache to use the fastrouter (add --cache <n>)\n");
@@ -554,7 +610,7 @@ int fastrouter_opt(int i, char *optarg) {
switch(i) {
case LONG_ARGS_FASTROUTER:
ufr.socket_name = optarg;
uwsgi_fastrouter_new_socket(generate_socket_name(optarg));
return 1;
case LONG_ARGS_FASTROUTER_SUBSCRIPTION_SERVER:
ufr.subscription_server = optarg;
@@ -575,6 +631,9 @@ int fastrouter_opt(int i, char *optarg) {
case LONG_ARGS_FASTROUTER_TIMEOUT:
ufr.socket_timeout = atoi(optarg);
return -1;
case LONG_ARGS_FASTROUTER_SUBSCRIPTION_SLOT:
ufr.subscription_slot = atoi(optarg);
return 1;
}
return 0;
}
+1 -1
View File
@@ -710,7 +710,7 @@ void http_loop() {
#ifndef __sun__
// fd passing: PERFORMANCE EXTREME BOOST !!!
if (uhttp_session->pass_fd && !uhttp_session->remains) {
if (uhttp_session->pass_fd && !uhttp_session->remains && !uwsgi.no_fd_passing) {
msg.msg_name = NULL;
msg.msg_namelen = 0;
msg.msg_iov = uhttp_session->iov;
+4 -2
View File
@@ -114,7 +114,6 @@ int init_uwsgi_app(int loader, void *arg1, struct wsgi_request *wsgi_req, PyThre
uwsgi_log("%s = %s\n", PyString_AsString(k), PyString_AsString(env_value));
if (PyObject_SetItem(py_environ, k, env_value)) {
uwsgi_log("cazzo\n");
PyErr_Print();
}
@@ -521,6 +520,9 @@ PyObject *uwsgi_file_loader(void *arg1) {
PyObject *wsgi_file_module, *wsgi_file_dict;
PyObject *wsgi_file_callable;
char *callable = up.callable;
if (!callable) callable = "application";
wsgi_file_module = uwsgi_pyimport_by_filename("uwsgi_wsgi_file", filename);
// no need to check here for module import as it is already done by uwsgi_pyimport_by_file
@@ -530,7 +532,7 @@ PyObject *uwsgi_file_loader(void *arg1) {
exit(1);
}
wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, "application");
wsgi_file_callable = PyDict_GetItemString(wsgi_file_dict, callable);
if (!wsgi_file_callable) {
PyErr_Print();
uwsgi_log( "unable to find \"application\" callable in file %s\n", filename);
+16
View File
@@ -428,6 +428,20 @@ void init_uwsgi_embedded_module() {
exit(1);
}
PyObject *uwsgi_py_version_info = PyTuple_New(5);
PyTuple_SetItem(uwsgi_py_version_info, 0, PyInt_FromLong(UWSGI_VERSION_BASE));
PyTuple_SetItem(uwsgi_py_version_info, 1, PyInt_FromLong(UWSGI_VERSION_MAJOR));
PyTuple_SetItem(uwsgi_py_version_info, 2, PyInt_FromLong(UWSGI_VERSION_MINOR));
PyTuple_SetItem(uwsgi_py_version_info, 3, PyInt_FromLong(UWSGI_VERSION_REVISION));
PyTuple_SetItem(uwsgi_py_version_info, 4, PyString_FromString(UWSGI_VERSION_CUSTOM));
if (PyDict_SetItemString(up.embedded_dict, "version_info", uwsgi_py_version_info)) {
PyErr_Print();
exit(1);
}
if (PyDict_SetItemString(up.embedded_dict, "hostname", PyString_FromStringAndSize(uwsgi.hostname, uwsgi.hostname_len))) {
PyErr_Print();
exit(1);
@@ -719,6 +733,7 @@ int uwsgi_python_manage_options(int i, char *optarg) {
return 1;
#ifdef UWSGI_INI
case LONG_ARGS_INI_PASTE:
uwsgi.ini = optarg;
if (uwsgi.ini[0] != '/') {
@@ -728,6 +743,7 @@ int uwsgi_python_manage_options(int i, char *optarg) {
up.paste = uwsgi_concat2("config:", uwsgi.ini);
}
return 1;
#endif
case LONG_ARGS_PASTE:
up.paste = optarg;
return 1;
+10 -6
View File
@@ -1192,8 +1192,7 @@ PyObject *py_uwsgi_send_spool(PyObject * self, PyObject * args, PyObject *kw) {
}
else {
Py_DECREF(zero);
Py_INCREF(Py_None);
return Py_None;
return PyErr_Format(PyExc_ValueError, "spooler packet cannot be more than %d bytes", uwsgi.buffer_size);
}
}
else {
@@ -1555,7 +1554,6 @@ PyObject *uwsgi_Iter_next(PyObject * self) {
ui->has_cl = 1;
ui->size = uh.pktsize;
ui->sent = 0;
uwsgi_log("NEED TO READ %d\n", uh.pktsize);
}
}
@@ -2209,8 +2207,10 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
}
// close connection on the worker
fclose(wsgi_req->async_post);
wsgi_req->fd_closed = 1;
if (PyTuple_Size(args) == 0) {
fclose(wsgi_req->async_post);
wsgi_req->fd_closed = 1;
}
clear:
Py_INCREF(Py_None);
@@ -2219,8 +2219,13 @@ PyObject *py_uwsgi_grunt(PyObject * self, PyObject * args) {
#ifdef UWSGI_SPOOLER
static PyMethodDef uwsgi_spooler_methods[] = {
#ifdef PYTHREE
{"send_to_spooler", (PyCFunction) py_uwsgi_send_spool, METH_VARARGS | METH_KEYWORDS, ""},
{"spool", (PyCFunction) py_uwsgi_send_spool, METH_VARARGS | METH_KEYWORDS, ""},
#else
{"send_to_spooler", (PyCFunction) py_uwsgi_send_spool, METH_KEYWORDS, ""},
{"spool", (PyCFunction) py_uwsgi_send_spool, METH_KEYWORDS, ""},
#endif
{"set_spooler_frequency", py_uwsgi_spooler_freq, METH_VARARGS, ""},
{"spooler_jobs", py_uwsgi_spooler_jobs, METH_VARARGS, ""},
{NULL, NULL},
@@ -2338,7 +2343,6 @@ static PyMethodDef uwsgi_advanced_methods[] = {
{"load_plugin", py_uwsgi_load_plugin, METH_VARARGS, ""},
{"lock", py_uwsgi_lock, METH_VARARGS, ""},
{"unlock", py_uwsgi_unlock, METH_VARARGS, ""},
{"send", py_uwsgi_send, METH_VARARGS, ""},
{"cl", py_uwsgi_cl, METH_VARARGS, ""},
{"listen_queue", py_uwsgi_listen_queue, METH_VARARGS, ""},
+4
View File
@@ -22,6 +22,10 @@
#define HAS_NOT_PyFrame_GetLineNumber
#endif
#if PY_MAJOR_VERSION == 3 && PY_MINOR_VERSION < 2
#define HAS_NOT_PyFrame_GetLineNumber
#endif
#if PY_MAJOR_VERSION > 2
#define PYTHREE
#endif
+35 -18
View File
@@ -103,7 +103,7 @@ static void uwsgi_Input_free(uwsgi_Input *self) {
static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
long len = 0;
size_t remains;
size_t remains, tmp_pos = 0;
ssize_t rlen;
char *tmp_buf;
PyObject *res;
@@ -113,10 +113,24 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
}
// return empty string if no post_cl or pos >= post_cl
if (!self->wsgi_req->post_cl || (size_t) self->pos >= self->wsgi_req->post_cl) {
if ((!self->wsgi_req->post_cl || (size_t) self->pos >= self->wsgi_req->post_cl ) && !self->readline_pos) {
return PyString_FromString("");
}
// some residual data ?
if (self->readline_pos && self->readline_size) {
if (len > 0) {
if ((size_t) len < (self->readline_size - self->readline_pos)) {
res = PyString_FromStringAndSize(self->readline + self->readline_pos, len);
self->readline_pos+=len;
if (self->readline_pos >= self->readline_size) self->readline_pos = 0;
return res;
}
}
self->readline_pos = 0;
return PyString_FromStringAndSize(self->readline + self->readline_pos, self->readline_size - self->readline_pos);
}
// return the whole input
if (len <= 0) {
remains = self->wsgi_req->post_cl;
@@ -125,7 +139,7 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
remains = len ;
}
if (remains + self->pos > self->wsgi_req->post_cl) {
if (remains + self->pos > self->wsgi_req->post_cl) {
remains = self->wsgi_req->post_cl - self->pos;
}
@@ -134,7 +148,7 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
}
if (uwsgi.post_buffering > 0) {
res = PyString_FromStringAndSize( self->wsgi_req->post_buffering_buf, remains);
res = PyString_FromStringAndSize( self->wsgi_req->post_buffering_buf+self->pos, remains);
self->pos += remains;
return res;
}
@@ -143,23 +157,26 @@ static PyObject *uwsgi_Input_read(uwsgi_Input *self, PyObject *args) {
tmp_buf = uwsgi_malloc(remains);
if (uwsgi_waitfd(self->wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
free(tmp_buf);
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data");
while(remains) {
if (uwsgi_waitfd(self->wsgi_req->poll.fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]) <= 0) {
free(tmp_buf);
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error waiting for wsgi.input data");
}
rlen = read(self->wsgi_req->poll.fd, tmp_buf+tmp_pos, remains);
if (rlen < 0) {
free(tmp_buf);
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
}
tmp_pos += rlen;
remains -= rlen;
}
rlen = read(self->wsgi_req->poll.fd, tmp_buf, remains);
if (rlen < 0) {
free(tmp_buf);
UWSGI_GET_GIL
return PyErr_Format(PyExc_IOError, "error reading wsgi.input data");
}
self->pos += rlen;
UWSGI_GET_GIL
res = PyString_FromStringAndSize(tmp_buf, rlen);
self->pos += tmp_pos;
res = PyString_FromStringAndSize(tmp_buf, tmp_pos);
free(tmp_buf);
return res;
+39 -15
View File
@@ -13,7 +13,6 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
PyObject *headers, *head;
PyObject *h_key, *h_value;
int i, j;
struct uwsgi_header uh;
PyObject *exc_info = NULL;
struct wsgi_request *wsgi_req = current_wsgi_req();
@@ -70,10 +69,8 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
}
wsgi_req->hvec[0].iov_len = wsgi_req->protocol_len;
uh.pktsize = wsgi_req->hvec[0].iov_len;
wsgi_req->hvec[1].iov_base = " ";
wsgi_req->hvec[1].iov_len = 1;
uh.pktsize += wsgi_req->hvec[1].iov_len;
#ifdef PYTHREE
wsgi_req->hvec[2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
wsgi_req->hvec[2].iov_len = strlen(wsgi_req->hvec[2].iov_base);
@@ -81,18 +78,15 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[2].iov_base = PyString_AsString(head);
wsgi_req->hvec[2].iov_len = PyString_Size(head);
#endif
uh.pktsize += wsgi_req->hvec[2].iov_len;
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;
}
else {
// drop http status on cgi mode
base = 3;
wsgi_req->hvec[0].iov_base = "Status: ";
wsgi_req->hvec[0].iov_len = 8;
uh.pktsize = wsgi_req->hvec[0].iov_len;
#ifdef PYTHREE
wsgi_req->hvec[1].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(head));
wsgi_req->hvec[1].iov_len = strlen(wsgi_req->hvec[1].iov_base);
@@ -100,11 +94,9 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[1].iov_base = PyString_AsString(head);
wsgi_req->hvec[1].iov_len = PyString_Size(head);
#endif
uh.pktsize += wsgi_req->hvec[1].iov_len;
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;
}
headers = PyTuple_GetItem(args, 1);
@@ -146,10 +138,8 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[j].iov_base = PyString_AsString(h_key);
wsgi_req->hvec[j].iov_len = PyString_Size(h_key);
#endif
uh.pktsize += wsgi_req->hvec[j].iov_len;
wsgi_req->hvec[j + 1].iov_base = h_sep;
wsgi_req->hvec[j + 1].iov_len = H_SEP_SIZE;
uh.pktsize += wsgi_req->hvec[j+1].iov_len;
#ifdef PYTHREE
wsgi_req->hvec[j + 2].iov_base = PyBytes_AsString(PyUnicode_AsASCIIString(h_value));
wsgi_req->hvec[j + 2].iov_len = strlen(wsgi_req->hvec[j + 2].iov_base);
@@ -158,29 +148,63 @@ PyObject *py_uwsgi_spit(PyObject * self, PyObject * args) {
wsgi_req->hvec[j + 2].iov_len = PyString_Size(h_value);
#endif
uh.pktsize += wsgi_req->hvec[j+2].iov_len;
wsgi_req->hvec[j + 3].iov_base = nl;
wsgi_req->hvec[j + 3].iov_len = NL_SIZE;
uh.pktsize += wsgi_req->hvec[j+3].iov_len;
//uwsgi_log( "%.*s: %.*s\n", wsgi_req->hvec[j].iov_len, (char *)wsgi_req->hvec[j].iov_base, wsgi_req->hvec[j+2].iov_len, (char *) wsgi_req->hvec[j+2].iov_base);
}
j = (i * 4) + base;
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
if (wsgi_req->header_cnt+1 <= uwsgi.max_vars) {
wsgi_req->header_cnt++;
wsgi_req->hvec[j].iov_base = ah->value;
wsgi_req->hvec[j].iov_len = ah->len;
j++;
wsgi_req->hvec[j].iov_base = nl;
wsgi_req->hvec[j].iov_len = NL_SIZE;
j++;
ah = ah->next;
}
else {
uwsgi_log("no more space in iovec. consider increasing max-vars...\n");
break;
}
}
// \r\n
j = (i * 4) + base;
wsgi_req->hvec[j].iov_base = nl;
wsgi_req->hvec[j].iov_len = NL_SIZE;
uh.pktsize += wsgi_req->hvec[j].iov_len;
#ifdef __sun__
int remains = j + 1;
int iov_size;
struct iovec* iov_ptr = wsgi_req->hvec;
ssize_t iov_ret;
while(remains) {
iov_size = UMIN(remains, IOV_MAX);
UWSGI_RELEASE_GIL
iov_ret = wsgi_req->socket->proto_writev_header(wsgi_req, iov_ptr, iov_size);
UWSGI_GET_GIL
if (iov_ret < 0) {
uwsgi_error("writev()");
}
wsgi_req->headers_size += iov_ret;
iov_ptr += iov_size;
remains -= iov_size;
}
#else
UWSGI_RELEASE_GIL
wsgi_req->headers_size = wsgi_req->socket->proto_writev_header(wsgi_req, wsgi_req->hvec, j + 1);
UWSGI_GET_GIL
if (wsgi_req->headers_size < 0) {
uwsgi_error("writev()");
}
#endif
//uwsgi_log("%d %p\n", wsgi_req->poll.fd, up.wsgi_writeout);
Py_INCREF(up.wsgi_writeout);
+2 -1
View File
@@ -17,7 +17,7 @@ uint16_t proto_base_add_uwsgi_header(struct wsgi_request *wsgi_req, char *key, u
key[i] = '_';
}
else {
key[i] = toupper(key[i]);
key[i] = toupper((int)key[i]);
}
}
@@ -90,6 +90,7 @@ uint16_t proto_base_add_uwsgi_var(struct wsgi_request * wsgi_req, char *key, uin
int uwsgi_proto_base_accept(struct wsgi_request *wsgi_req, int fd) {
wsgi_req->c_len = sizeof(struct sockaddr_un);
return accept(fd, (struct sockaddr *) &wsgi_req->c_addr, (socklen_t *) & wsgi_req->c_len);
}
+10 -9
View File
@@ -89,6 +89,8 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
char *ptr = wsgi_req->proto_parser_buf;
char *base = ptr;
char *query_string = NULL;
char ip[INET_ADDRSTRLEN+1];
struct sockaddr_in *http_sin = (struct sockaddr_in *) &wsgi_req->c_addr;
// REQUEST_METHOD
while (ptr < watermark) {
@@ -146,15 +148,14 @@ static int http_parse(struct wsgi_request *wsgi_req, char *watermark) {
// SERVER_PORT
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "3031", 4);
/*
// REMOTE_ADDR
if (inet_ntop(AF_INET, &h_session->ip_addr, h_session->ip, INET_ADDRSTRLEN)) {
h_session->uh.pktsize += proto_base_add_uwsgi_var(h_session->iov, h_session->uss+c, h_session->uss+c+2, "REMOTE_ADDR", 11, h_session->ip, strlen(h_session->ip));
}
else {
uwsgi_error("inet_ntop()");
}
*/
// REMOTE_ADDR
memset(ip, 0, INET_ADDRSTRLEN+1);
if (inet_ntop(AF_INET, (void *) &http_sin->sin_addr.s_addr, ip, INET_ADDRSTRLEN)) {
wsgi_req->uh.pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, ip, strlen(ip));
}
else {
uwsgi_error("inet_ntop()");
}
//HEADERS
base = ptr;
+3
View File
@@ -84,6 +84,9 @@ int uwsgi_proto_uwsgi_parser(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
#endif
if (uwsgi.no_fd_passing)
return UWSGI_OK;
cmsg = CMSG_FIRSTHDR(&wsgi_req->msg);
while (cmsg != NULL) {
if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type && SCM_RIGHTS) {
+17 -1
View File
@@ -1242,7 +1242,16 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
if (st.st_mtime <= ims) {
wsgi_req->status = 304;
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, " 304 Not Modified\r\n\r\n", 21);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, " 304 Not Modified\r\n", 19);
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
ah = ah->next;
}
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
return 0;
}
}
@@ -1256,6 +1265,13 @@ int uwsgi_file_serve(struct wsgi_request *wsgi_req, char *document_root, uint16_
wsgi_req->headers_size = wsgi_req->socket->proto_write_header(wsgi_req, wsgi_req->protocol, wsgi_req->protocol_len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, " 200 OK\r\n", 9);
struct uwsgi_string_list *ah = uwsgi.additional_headers;
while(ah) {
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, ah->value, ah->len);
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "\r\n", 2);
ah = ah->next;
}
if (uwsgi.file_serve_mode == 1) {
wsgi_req->header_cnt = 2;
wsgi_req->headers_size += wsgi_req->socket->proto_write_header(wsgi_req, "X-Accel-Redirect: ", 18);
+1 -1
View File
@@ -51,7 +51,7 @@ class uWSGIDistribution(Distribution):
setup(name='uWSGI',
version='0.9.8-dev',
version=uc.uwsgi_version,
description='The uWSGI server',
author='Unbit',
author_email='info@unbit.it',
+180 -21
View File
@@ -6,6 +6,7 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
int serverfd;
struct sockaddr_un *uws_addr;
socklen_t len;
// leave 1 byte for abstract namespace (108 linux -> 104 bsd/mac)
if (strlen(socket_name) > 102) {
@@ -13,6 +14,13 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
uwsgi_nuclear_blast();
}
if (socket_name[0] == '@') {
abstract_socket = 1;
}
else if (strlen(socket_name) > 1 && socket_name[0] == '\\' && socket_name[1] == '0') {
abstract_socket = 1;
}
uws_addr = malloc(sizeof(struct sockaddr_un));
if (uws_addr == NULL) {
uwsgi_error("malloc()");
@@ -36,12 +44,24 @@ int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abst
}
uws_addr->sun_family = AF_UNIX;
memcpy(uws_addr->sun_path + abstract_socket, socket_name, 102);
if (socket_name[0] == '@') {
memcpy(uws_addr->sun_path + abstract_socket, socket_name+1, UMIN(strlen(socket_name+1), 101));
len = strlen(socket_name) + 1;
}
else if (strlen(socket_name) > 1 && socket_name[0] == '\\' && socket_name[1] == '0') {
memcpy(uws_addr->sun_path + abstract_socket, socket_name+2, UMIN(strlen(socket_name+2), 101));
len = strlen(socket_name+1) + 1;
}
else {
memcpy(uws_addr->sun_path + abstract_socket, socket_name, UMIN(strlen(socket_name), 102));
len = strlen(socket_name);
}
#ifdef __HAIKU__
if (bind(serverfd, (struct sockaddr *) uws_addr, sizeof(struct sockaddr_un))) {
#else
if (bind(serverfd, (struct sockaddr *) uws_addr, strlen(socket_name) + abstract_socket + ((void *) uws_addr->sun_path - (void *) uws_addr)) != 0) {
if (bind(serverfd, (struct sockaddr *) uws_addr, len + ((void *) uws_addr->sun_path - (void *) uws_addr)) != 0) {
#endif
uwsgi_error("bind()");
uwsgi_nuclear_blast();
@@ -251,11 +271,23 @@ int connect_to_unix(char *socket_name, int timeout, int async) {
struct pollfd uwsgi_poll;
struct sockaddr_un uws_addr;
socklen_t un_size = sizeof(struct sockaddr_un);
memset(&uws_addr, 0, sizeof(struct sockaddr_un));
uws_addr.sun_family = AF_UNIX;
memcpy(uws_addr.sun_path, socket_name, 102);
if (socket_name[0] == '@'){
un_size = sizeof(uws_addr.sun_family) + strlen(socket_name) + 1;
memcpy(uws_addr.sun_path+1, socket_name+1, UMIN(strlen(socket_name+1), 101));
}
else if (strlen(socket_name) > 1 && socket_name[0] == '\\' && socket_name[1] == '0') {
un_size = sizeof(uws_addr.sun_family) + strlen(socket_name+1) + 1;
memcpy(uws_addr.sun_path+1, socket_name+2, UMIN(strlen(socket_name+2), 101));
}
else {
memcpy(uws_addr.sun_path, socket_name, UMIN(strlen(socket_name), 102));
}
uwsgi_poll.fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (uwsgi_poll.fd < 0) {
@@ -265,7 +297,7 @@ int connect_to_unix(char *socket_name, int timeout, int async) {
uwsgi_poll.events = POLLIN;
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &uws_addr, sizeof(struct sockaddr_un), timeout, async)) {
if (timed_connect(&uwsgi_poll, (const struct sockaddr *) &uws_addr, un_size, timeout, async)) {
uwsgi_error("connect()");
close(uwsgi_poll.fd);
return -1;
@@ -316,7 +348,6 @@ char *generate_socket_name(char *socket_name) {
char *asterisk = strchr(socket_name, '*');
char *new_socket;
char *tcp_port;
int i;
char *ptr = socket_name;
@@ -345,6 +376,10 @@ char *generate_socket_name(char *socket_name) {
if (asterisk) {
#ifndef UWSGI_HAS_IFADDRS
uwsgi_log("your system does not support ifaddrs subsystem\n");
#else
char *new_socket;
uwsgi_log("generate_socket_name(%s)\n", socket_name);
// get all the AF_INET addresses available
struct ifaddrs *ifap = NULL, *ifa, *ifaf;
@@ -381,24 +416,69 @@ char *generate_socket_name(char *socket_name) {
}
uwsgi_log("unable to find avalid socket address\n");
#endif
uwsgi_nuclear_blast();
}
return socket_name;
}
socklen_t socket_to_un_addr(char *socket_name, struct sockaddr_un *sun_addr) {
size_t len = strlen(socket_name);
if (len > 102) {
uwsgi_log("invalid UNIX socket address: %s\n", socket_name);
uwsgi_nuclear_blast();
}
memset(sun_addr, 0, sizeof(struct sockaddr_un));
sun_addr->sun_family = AF_UNIX;
// abstract socket
if (socket_name[0] == '@') {
memcpy(sun_addr->sun_path+1, socket_name+1, UMIN(len-1, 101));
len = strlen(socket_name) + 1;
}
else if (len > 1 && socket_name[0] == '\\' && socket_name[1] == '0') {
memcpy(sun_addr->sun_path+1, socket_name+2, UMIN(len-2, 101));
len = strlen(socket_name+1) + 1;
}
else {
memcpy(sun_addr->sun_path, socket_name, UMIN(len, 102));
}
return sizeof(sun_addr->sun_family)+len;
}
socklen_t socket_to_in_addr(char *socket_name, char *port, struct sockaddr_in *sin_addr) {
memset(sin_addr, 0, sizeof(struct sockaddr_in));
sin_addr->sin_family = AF_INET;
if (port) {
port[0] = 0;
sin_addr->sin_port = htons(atoi(port + 1));
}
if (socket_name[0] == 0) {
sin_addr->sin_addr.s_addr = INADDR_ANY;
}
else {
sin_addr->sin_addr.s_addr = inet_addr(socket_name);
}
return sizeof(struct sockaddr_in);
}
int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
int serverfd;
struct sockaddr_in uws_addr;
int reuse = 1;
memset(&uws_addr, 0, sizeof(struct sockaddr_in));
uws_addr.sin_family = AF_INET;
if (tcp_port) {
tcp_port[0] = 0;
uws_addr.sin_port = htons(atoi(tcp_port + 1));
}
socket_to_in_addr(socket_name, tcp_port, &uws_addr);
serverfd = socket(AF_INET, SOCK_STREAM, 0);
if (serverfd < 0) {
@@ -406,14 +486,6 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
uwsgi_nuclear_blast();
}
if (socket_name[0] == 0) {
uws_addr.sin_addr.s_addr = INADDR_ANY;
}
else {
uws_addr.sin_addr.s_addr = inet_addr(socket_name);
}
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
uwsgi_error("setsockopt()");
uwsgi_nuclear_blast();
@@ -568,6 +640,48 @@ int uwsgi_get_socket_num(struct uwsgi_socket *uwsgi_sock) {
return -1;
}
int uwsgi_get_shared_socket_num(struct uwsgi_socket *uwsgi_sock) {
int count = 0;
struct uwsgi_socket *current_sock = uwsgi.shared_sockets;
while(current_sock) {
if (uwsgi_sock == current_sock) {
return count;
}
count++;
current_sock = current_sock->next;
}
return -1;
}
struct uwsgi_socket *uwsgi_new_shared_socket(char *name) {
struct uwsgi_socket *uwsgi_sock = uwsgi.shared_sockets, *old_uwsgi_sock;
if (!uwsgi_sock) {
uwsgi.shared_sockets = uwsgi_malloc(sizeof(struct uwsgi_socket));
uwsgi_sock = uwsgi.shared_sockets;
}
else {
while(uwsgi_sock) {
old_uwsgi_sock = uwsgi_sock;
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_socket));
old_uwsgi_sock->next = uwsgi_sock;
}
memset(uwsgi_sock, 0, sizeof(struct uwsgi_socket));
uwsgi_sock->name = name;
return uwsgi_sock;
}
struct uwsgi_socket *uwsgi_new_socket(char *name) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets, *old_uwsgi_sock;
@@ -597,6 +711,7 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
socklen_t socket_type_len;
union uwsgi_sockaddr_ptr gsa, isa;
union uwsgi_sockaddr usa;
int abstract = 0;
socket_type_len = sizeof(struct sockaddr_un);
gsa.sa = &usa.sa;
@@ -606,7 +721,8 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
return;
}
if (gsa.sa->sa_family == AF_UNIX) {
if (!strcmp(usa.sa_un.sun_path, uwsgi_sock->name)) {
if (usa.sa_un.sun_path[0] == 0) abstract = 1;
if (!strcmp(usa.sa_un.sun_path+abstract, uwsgi_sock->name+abstract)) {
uwsgi_sock->fd = fd;
uwsgi_sock->family = AF_UNIX;
uwsgi_sock->bound = 1;
@@ -691,3 +807,46 @@ struct uwsgi_socket *uwsgi_del_socket(struct uwsgi_socket *uwsgi_sock) {
return NULL;
}
int uwsgi_get_shared_socket_fd_by_num(int num) {
int counter = 0;
struct uwsgi_socket *found_sock = NULL, *uwsgi_sock = uwsgi.shared_sockets;
while(uwsgi_sock) {
if (counter == num) {
found_sock = uwsgi_sock;
break;
}
counter++;
uwsgi_sock = uwsgi_sock->next;
}
if (found_sock) {
return found_sock->fd;
}
return -1;
}
void uwsgi_add_sockets_to_queue(int queue) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
event_queue_add_fd_read(queue, uwsgi_sock->fd);
uwsgi_sock = uwsgi_sock->next;
}
}
void uwsgi_del_sockets_from_queue(int queue) {
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
event_queue_del_fd(queue, uwsgi_sock->fd, event_queue_read());
uwsgi_sock = uwsgi_sock->next;
}
}
+4
View File
@@ -126,10 +126,14 @@ void spooler() {
// asked by Marco Beri
#ifdef __HAIKU__
#ifdef UWSGI_DEBUG
uwsgi_log("lowering spooler priority to %d\n", B_LOW_PRIORITY);
#endif
set_thread_priority(find_thread(NULL), B_LOW_PRIORITY);
#else
#ifdef UWSGI_DEBUG
uwsgi_log("lowering spooler priority to %d\n", PRIO_MAX);
#endif
setpriority(PRIO_PROCESS, getpid(), PRIO_MAX);
#endif
+1 -1
View File
@@ -6,7 +6,7 @@ def application(env, start_response):
start_response( '200 OK', [ ('Content-Type','text/html') ])
start_time = time.time()
for i in range(1,100000):
uwsgi.green_schedule()
uwsgi.suspend()
# print every 100
if i % 100 == 0:
yield "<h1>%d</h1>\n" % i
+9 -2
View File
@@ -5,12 +5,19 @@ def application(env, start_response):
start_response('200 Ok', [('Content-type', 'text/plain')])
#for x in env['wsgi.input']:
# yield x
return env['wsgi.input'].readlines()
body = env['wsgi.input'].readline()
print body
body += env['wsgi.input'].read(100)
body += env['wsgi.input'].read(100)
body += env['wsgi.input'].read()
return body
else:
start_response('200 Ok', [('Content-type', 'text/html')])
return """
<form method="POST" enctype="multipart/form-data">
<input type="file" name="file" />
<textarea name="pluto">
</textarea>
<input type="test" name="pippo" />
<input type="submit" value="invia" />
</form>
"""
+126 -52
View File
@@ -259,6 +259,50 @@ void log_zeromq(char *node) {
}
#endif
void log_socket(char *socket_name) {
int family = AF_UNIX;
uwsgi.log_socket_addr = uwsgi_malloc(sizeof(union uwsgi_sockaddr));
char *colon = strchr(socket_name, ':');
if (colon) {
family = AF_INET;
uwsgi.log_socket_size = socket_to_in_addr(socket_name, colon, &uwsgi.log_socket_addr->sa_in);
}
else {
uwsgi.log_socket_size = socket_to_un_addr(socket_name, &uwsgi.log_socket_addr->sa_un);
}
uwsgi.log_socket_fd = socket(family, SOCK_DGRAM, 0);
if (uwsgi.log_socket_fd < 0) {
uwsgi_error("socket()");
uwsgi_nuclear_blast();
}
// create log connection with the master
if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
uwsgi_error("socketpair()\n");
exit(1);
}
uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[0]);
uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[1]);
if (uwsgi.shared->worker_log_pipe[1] != 1) {
if (dup2(uwsgi.shared->worker_log_pipe[1], 1) < 0) {
uwsgi_error("dup2()");
exit(1);
}
}
if (dup2(1, 2) < 0) {
uwsgi_error("dup2()");
exit(1);
}
}
void log_syslog(char *syslog_opts) {
@@ -371,69 +415,75 @@ void internal_server_error(struct wsgi_request *wsgi_req, char *message) {
uwsgi.wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, message, strlen(message));
}
void uwsgi_as_root() {
#ifdef __linux__
void uwsgi_set_cgroup() {
char *cgroup_taskfile;
int i;
FILE *cgroup;
char *cgroup_opt;
if (!uwsgi.cgroup) return;
if (mkdir(uwsgi.cgroup, 0700)) {
uwsgi_log("using Linux cgroup %s\n", uwsgi.cgroup);
}
else {
uwsgi_log("created Linux cgroup %s\n", uwsgi.cgroup);
}
uwsgi_error("mkdir()");
cgroup_taskfile = uwsgi_concat2(uwsgi.cgroup, "/tasks");
cgroup = fopen(cgroup_taskfile, "w");
if (!cgroup) {
uwsgi_error_open(cgroup_taskfile);
exit(1);
}
if (fprintf(cgroup, "%d", (int) getpid()) <= 0) {
uwsgi_log("could not set cgroup\n");
exit(1);
}
uwsgi_log("moved process %d to cgroup %s\n", (int) getpid(), cgroup_taskfile);
fclose(cgroup);
free(cgroup_taskfile);
for (i = 0; i < uwsgi.cgroup_opt_cnt; i++) {
cgroup_opt = strchr(uwsgi.cgroup_opt[i], '=');
if (!cgroup_opt) {
cgroup_opt = strchr(uwsgi.cgroup_opt[i], ':');
if (!cgroup_opt) {
uwsgi_log("invalid cgroup-opt syntax\n");
exit(1);
}
}
cgroup_opt[0] = 0;
cgroup_opt++;
cgroup_taskfile = uwsgi_concat3(uwsgi.cgroup, "/", uwsgi.cgroup_opt[i]);
cgroup = fopen(cgroup_taskfile, "w");
if (!cgroup) {
uwsgi_error_open(cgroup_taskfile);
exit(1);
}
if (fprintf(cgroup, "%s\n", cgroup_opt) < 0) {
uwsgi_log("could not set cgroup option %s to %s\n", uwsgi.cgroup_opt[i], cgroup_opt);
exit(1);
}
fclose(cgroup);
free(cgroup_taskfile);
}
}
#endif
void uwsgi_as_root() {
if (!getuid()) {
if (!uwsgi.master_as_root && !uwsgi.uidname) {
uwsgi_log("uWSGI running as root, you can use --uid/--gid/--chroot options\n");
}
#ifdef __linux__
if (uwsgi.cgroup) {
if (mkdir(uwsgi.cgroup, S_IRWXU | S_IROTH | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)) {
uwsgi_log("using Linux cgroup %s\n", uwsgi.cgroup);
}
else {
uwsgi_log("created Linux cgroup %s\n", uwsgi.cgroup);
}
cgroup_taskfile = uwsgi_concat2(uwsgi.cgroup, "/tasks");
cgroup = fopen(cgroup_taskfile, "w");
if (!cgroup) {
uwsgi_error_open(cgroup_taskfile);
exit(1);
}
if (fprintf(cgroup, "%d\n", (int) getpid()) < 0) {
uwsgi_log("could not set cgroup\n");
exit(1);
}
fclose(cgroup);
free(cgroup_taskfile);
for (i = 0; i < uwsgi.cgroup_opt_cnt; i++) {
cgroup_opt = strchr(uwsgi.cgroup_opt[i], '=');
if (!cgroup_opt) {
cgroup_opt = strchr(uwsgi.cgroup_opt[i], ':');
if (!cgroup_opt) {
uwsgi_log("invalid cgroup-opt syntax\n");
exit(1);
}
}
cgroup_opt[0] = 0;
cgroup_opt++;
cgroup_taskfile = uwsgi_concat3(uwsgi.cgroup, "/", uwsgi.cgroup_opt[i]);
cgroup = fopen(cgroup_taskfile, "w");
if (!cgroup) {
uwsgi_error_open(cgroup_taskfile);
exit(1);
}
if (fprintf(cgroup, "%s\n", cgroup_opt) < 0) {
uwsgi_log("could not set cgroup option %s to %s\n", uwsgi.cgroup_opt[i], cgroup_opt);
exit(1);
}
fclose(cgroup);
free(cgroup_taskfile);
}
}
#endif
if (uwsgi.chroot && !uwsgi.reloads) {
if (!uwsgi.master_as_root)
uwsgi_log("chroot() to %s\n", uwsgi.chroot);
@@ -720,6 +770,9 @@ int wsgi_req_accept(struct wsgi_request *wsgi_req) {
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 {
uwsgi_log_verbose("master sent signal %d to worker %d\n", uwsgi_signal, uwsgi.mywid);
@@ -852,6 +905,7 @@ void uwsgi_log(const char *fmt, ...) {
va_list ap;
char logpkt[4096];
int rlen = 0;
int ret;
struct timeval tv;
char sftime[64];
@@ -876,9 +930,21 @@ void uwsgi_log(const char *fmt, ...) {
}
va_start(ap, fmt);
rlen += vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap);
ret = vsnprintf(logpkt + rlen, 4096 - rlen, fmt, ap);
va_end(ap);
if (ret >= 4096) {
char *tmp_buf = uwsgi_malloc(rlen + ret + 1);
memcpy(tmp_buf, logpkt, rlen);
va_start(ap, fmt);
ret = vsnprintf(tmp_buf + rlen, ret+1, fmt, ap);
va_end(ap);
rlen = write(2, tmp_buf, rlen+ret);
free(tmp_buf);
return;
}
rlen+=ret;
// do not check for errors
rlen = write(2, logpkt, rlen);
}
@@ -2166,6 +2232,7 @@ struct uwsgi_string_list *uwsgi_string_new_list(struct uwsgi_string_list **list,
}
uwsgi_string->value = value;
uwsgi_string->len = strlen(value);
uwsgi_string->next = NULL;
return uwsgi_string;
@@ -2195,3 +2262,10 @@ void uwsgi_string_del_list(struct uwsgi_string_list **list, struct uwsgi_string_
}
}
void uwsgi_sig_pause() {
sigset_t mask;
sigemptyset(&mask);
sigsuspend(&mask);
}
+375 -217
View File
@@ -31,7 +31,9 @@ static char *short_options = NULL;
static char *base_short_options = "s:p:t:x:d:l:v:b:mcaCTiMhrR:z:A:Q:Ly:";
UWSGI_DECLARE_EMBEDDED_PLUGINS static struct option long_base_options[] = {
UWSGI_DECLARE_EMBEDDED_PLUGINS;
static struct option long_base_options[] = {
{"socket", required_argument, 0, 's'},
{"protocol", required_argument, 0, LONG_ARGS_PROTOCOL},
{"socket-protocol", required_argument, 0, LONG_ARGS_SOCKET_PROTOCOL},
@@ -62,17 +64,21 @@ UWSGI_DECLARE_EMBEDDED_PLUGINS static struct option long_base_options[] = {
{"single-interpreter", no_argument, 0, 'i'},
{"master", no_argument, 0, 'M'},
{"emperor", required_argument, 0, LONG_ARGS_EMPEROR},
{"early-emperor", no_argument, &uwsgi.early_emperor, 1},
{"emperor-amqp-vhost", required_argument, 0, LONG_ARGS_EMPEROR_AMQP_VHOST},
{"emperor-amqp-username", required_argument, 0, LONG_ARGS_EMPEROR_AMQP_USERNAME},
{"emperor-amqp-password", required_argument, 0, LONG_ARGS_EMPEROR_AMQP_PASSWORD},
{"vassals-inherit", required_argument, 0, LONG_ARGS_VASSALS_INHERIT},
{"auto-snapshot", optional_argument, 0, LONG_ARGS_AUTO_SNAPSHOT},
{"reload-mercy", required_argument, 0, LONG_ARGS_RELOAD_MERCY},
{"exit-on-reload", no_argument, &uwsgi.exit_on_reload, 1},
{"die-on-term", no_argument, &uwsgi.die_on_term, 1},
{"help", no_argument, 0, 'h'},
{"usage", no_argument, 0, 'h'},
{"reaper", no_argument, 0, 'r'},
{"max-requests", required_argument, 0, 'R'},
{"socket-timeout", required_argument, 0, 'z'},
{"no-fd-passing", no_argument, &uwsgi.no_fd_passing, 1},
{"sharedarea", required_argument, 0, 'A'},
{"cache", required_argument, 0, LONG_ARGS_CACHE},
{"cache-blocksize", required_argument, 0, LONG_ARGS_CACHE_BLOCKSIZE},
@@ -154,11 +160,14 @@ UWSGI_DECLARE_EMBEDDED_PLUGINS static struct option long_base_options[] = {
{"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-socket", required_argument, 0, LONG_ARGS_LOG_SOCKET},
#ifdef UWSGI_ZEROMQ
{"log-zeromq", required_argument, 0, LONG_ARGS_LOG_ZEROMQ},
#endif
{"log-master", no_argument, 0, LONG_ARGS_LOG_MASTER},
{"logdate", optional_argument, 0, LONG_ARGS_LOG_DATE},
{"log-date", optional_argument, 0, LONG_ARGS_LOG_DATE},
{"log-prefix", optional_argument, 0, LONG_ARGS_LOG_DATE},
{"log-zero", no_argument, 0, LONG_ARGS_LOG_ZERO},
{"log-slow", required_argument, 0, LONG_ARGS_LOG_SLOW},
{"log-4xx", no_argument, 0, LONG_ARGS_LOG_4xx},
@@ -170,6 +179,8 @@ UWSGI_DECLARE_EMBEDDED_PLUGINS static struct option long_base_options[] = {
{"chdir", required_argument, 0, LONG_ARGS_CHDIR},
{"chdir2", required_argument, 0, LONG_ARGS_CHDIR2},
{"lazy", no_argument, &uwsgi.lazy, 1},
{"cheap", no_argument, &uwsgi.cheap, 1},
{"idle", required_argument, 0, LONG_ARGS_IDLE},
{"mount", required_argument, 0, LONG_ARGS_MOUNT},
{"grunt", no_argument, &uwsgi.grunt, 1},
{"threads", required_argument, 0, LONG_ARGS_THREADS},
@@ -178,6 +189,7 @@ UWSGI_DECLARE_EMBEDDED_PLUGINS static struct option long_base_options[] = {
#ifdef UWSGI_ROUTING
{"routing", no_argument, &uwsgi.routing, 1},
#endif
{"add-header", required_argument, 0, LONG_ARGS_ADD_HEADER},
{"check-static", required_argument, 0, LONG_ARGS_CHECK_STATIC},
{"static-map", required_argument, 0, LONG_ARGS_STATIC_MAP},
{"file-serve-mode", required_argument, 0, LONG_ARGS_FILE_SERVE_MODE},
@@ -211,48 +223,48 @@ UWSGI_DECLARE_EMBEDDED_PLUGINS static struct option long_base_options[] = {
void uwsgi_configure(void) {
struct option *lopt = uwsgi.long_options;
struct option *aopt;
char *val;
struct option *aopt;
char *val;
int i;
int is_retry;
int found;
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
for (i = 0; i < uwsgi.exported_opts_cnt; i++) {
if (uwsgi.exported_opts[i]->configured)
continue;
if (uwsgi.exported_opts[i]->configured)
continue;
is_retry = 0;
retry:
retry:
found = 0;
lopt = uwsgi.long_options;;
while ((aopt = lopt)) {
if (!aopt->name)
break;
lopt = uwsgi.long_options;;
while ((aopt = lopt)) {
if (!aopt->name)
break;
if (!strcmp(aopt->name, uwsgi.exported_opts[i]->key)) {
if (!strcmp(aopt->name, uwsgi.exported_opts[i]->key)) {
found = 1;
val = uwsgi.exported_opts[i]->value;
val = uwsgi.exported_opts[i]->value;
if (aopt->flag)
*aopt->flag = aopt->val;
else if (val) {
if (aopt->has_arg == optional_argument) {
if (!strcasecmp("true", val)) {
val = NULL;
}
}
if (aopt->has_arg == no_argument) {
if (!strcasecmp("false", val) || val[0] == '0') {
lopt++;
continue;
}
}
manage_opt(aopt->val, val);
}
}
lopt++;
}
if (aopt->flag)
*aopt->flag = aopt->val;
else if (val) {
if (aopt->has_arg == optional_argument) {
if (!strcasecmp("true", val)) {
val = NULL;
}
}
if (aopt->has_arg == no_argument) {
if (!strcasecmp("false", val) || val[0] == '0') {
lopt++;
continue;
}
}
manage_opt(aopt->val, val);
}
}
lopt++;
}
if (!found && uwsgi.autoload && !is_retry) {
DIR *pdir;
@@ -262,7 +274,7 @@ retry:
uwsgi_fatal_error("opendir()");
}
while ((dp = readdir(pdir)) != NULL) {
if (!strncmp("_plugin.so", dp->d_name+(strlen(dp->d_name)-10), 19)) {
if (!strncmp("_plugin.so", dp->d_name + (strlen(dp->d_name) - 10), 19)) {
if (uwsgi_load_plugin(-1, dp->d_name, uwsgi.exported_opts[i]->key, 2)) {
uwsgi_log("option \"%s\" found in plugin %s\n", uwsgi.exported_opts[i]->key, dp->d_name);
found = 1;
@@ -279,7 +291,7 @@ retry:
}
closedir(pdir);
}
}
}
}
@@ -325,26 +337,26 @@ void warn_pipe() {
#ifdef UWSGI_THREADING
// in threading mode we need to use the cancel pthread subsystem
void wait_for_threads() {
int i, ret;
int i, ret;
pthread_mutex_lock(&uwsgi.six_feet_under_lock);
for(i=0;i<uwsgi.threads;i++) {
if (!pthread_equal(uwsgi.core[i]->thread_id, pthread_self())) {
pthread_cancel(uwsgi.core[i]->thread_id);
}
}
pthread_mutex_lock(&uwsgi.six_feet_under_lock);
for (i = 0; i < uwsgi.threads; i++) {
if (!pthread_equal(uwsgi.core[i]->thread_id, pthread_self())) {
pthread_cancel(uwsgi.core[i]->thread_id);
}
}
// wait for thread termination
for(i=0;i<uwsgi.threads;i++) {
if (!pthread_equal(uwsgi.core[i]->thread_id, pthread_self())) {
ret = pthread_join(uwsgi.core[i]->thread_id, NULL);
if (ret) {
uwsgi_log("pthread_join() = %d\n", ret);
}
}
}
// wait for thread termination
for (i = 0; i < uwsgi.threads; i++) {
if (!pthread_equal(uwsgi.core[i]->thread_id, pthread_self())) {
ret = pthread_join(uwsgi.core[i]->thread_id, NULL);
if (ret) {
uwsgi_log("pthread_join() = %d\n", ret);
}
}
}
pthread_mutex_unlock(&uwsgi.six_feet_under_lock);
pthread_mutex_unlock(&uwsgi.six_feet_under_lock);
}
#endif
@@ -360,7 +372,7 @@ void gracefully_kill(int signum) {
if (!uwsgi.core[wsgi_req->async_id]->in_request) {
exit(UWSGI_RELOAD_CODE);
}
return;
return;
// never here
}
#endif
@@ -396,12 +408,35 @@ void goodbye_cruel_world() {
void kill_them_all(int signum) {
int i;
uwsgi.to_hell = 1;
if (uwsgi.reload_mercy > 0) {
uwsgi.master_mercy = time(NULL) + uwsgi.reload_mercy;
}
else {
uwsgi.master_mercy = time(NULL) + 5;
}
uwsgi_log("SIGINT/SIGQUIT received...killing workers...\n");
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0)
kill(uwsgi.workers[i].pid, SIGINT);
}
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
kill(uwsgi.shared->spooler_pid, SIGKILL);
uwsgi_log("killed the spooler with pid %d\n", uwsgi.shared->spooler_pid);
}
#endif
if (uwsgi.emperor_pid >= 0) {
kill(uwsgi.emperor_pid, SIGKILL);
waitpid(uwsgi.emperor_pid, &i, 0);
uwsgi_log("killed the emperor with pid %d\n", uwsgi.emperor_pid);
}
for (i = 0; i < uwsgi.shared->daemons_cnt; i++) {
if (uwsgi.shared->daemons[i].pid > 0)
kill(uwsgi.shared->daemons[i].pid, SIGKILL);
@@ -415,12 +450,28 @@ void kill_them_all(int signum) {
void grace_them_all(int signum) {
int i;
uwsgi.to_heaven = 1;
int waitpid_status;
if (!uwsgi.lazy)
uwsgi.to_heaven = 1;
if (uwsgi.reload_mercy > 0) {
uwsgi.master_mercy = time(NULL) + uwsgi.reload_mercy;
}
#ifdef UWSGI_SPOOLER
if (uwsgi.spool_dir && uwsgi.shared->spooler_pid > 0) {
kill(uwsgi.shared->spooler_pid, SIGKILL);
uwsgi_log("killed the spooler with pid %d\n", uwsgi.shared->spooler_pid);
}
#endif
if (uwsgi.emperor_pid >= 0) {
kill(uwsgi.emperor_pid, SIGKILL);
waitpid(uwsgi.emperor_pid, &i, 0);
uwsgi_log("killed the emperor with pid %d\n", uwsgi.emperor_pid);
}
for (i = 0; i < uwsgi.shared->daemons_cnt; i++) {
if (uwsgi.shared->daemons[i].pid > 0)
kill(uwsgi.shared->daemons[i].pid, SIGKILL);
@@ -434,10 +485,32 @@ void grace_them_all(int signum) {
uwsgi_log("...gracefully killing workers...\n");
for (i = 1; i <= uwsgi.numproc; i++) {
if (uwsgi.workers[i].pid > 0)
if (uwsgi.auto_snapshot) {
if (uwsgi.workers[i].snapshot > 0) {
kill(uwsgi.workers[i].snapshot, SIGKILL);
if (waitpid(uwsgi.workers[i].snapshot, &waitpid_status, 0) < 0) {
uwsgi_error("waitpid()");
}
}
if (uwsgi.workers[i].pid > 0) {
if (uwsgi.auto_snapshot > 0 && i > uwsgi.auto_snapshot) {
uwsgi.workers[i].snapshot = 0;
kill(uwsgi.workers[i].pid, SIGHUP);
}
else {
uwsgi.workers[i].snapshot = uwsgi.workers[i].pid;
kill(uwsgi.workers[i].pid, SIGURG);
}
}
}
else if (uwsgi.workers[i].pid > 0)
kill(uwsgi.workers[i].pid, SIGHUP);
}
if (uwsgi.auto_snapshot) {
uwsgi.respawn_workers = 1;
}
}
void uwsgi_nuclear_blast() {
@@ -456,7 +529,9 @@ void uwsgi_nuclear_blast() {
void reap_them_all(int signum) {
int i;
uwsgi.to_heaven = 1;
if (!uwsgi.lazy)
uwsgi.to_heaven = 1;
for (i = 0; i < uwsgi.shared->daemons_cnt; i++) {
if (uwsgi.shared->daemons[i].pid > 0)
@@ -468,6 +543,12 @@ void reap_them_all(int signum) {
kill(uwsgi.gateways[i].pid, SIGKILL);
}
if (uwsgi.emperor_pid >= 0) {
kill(uwsgi.emperor_pid, SIGKILL);
waitpid(uwsgi.emperor_pid, &i, 0);
uwsgi_log("killed the emperor with pid %d\n", uwsgi.emperor_pid);
}
if (!uwsgi.workers)
return;
@@ -488,6 +569,23 @@ void harakiri() {
exit(0);
}
void snapshot_me(int signum) {
// wakeup !!!
if (uwsgi.snapshot) {
uwsgi.snapshot = 0;
return;
}
uwsgi.workers[uwsgi.mywid].manage_next_request = 0;
#ifdef UWSGI_THREADING
if (uwsgi.threads > 1) {
wait_for_threads();
}
#endif
uwsgi.snapshot = 1;
uwsgi_log("[snapshot] process %d taken\n", (int) getpid());
}
void stats(int signum) {
//fix this for better logging(this cause races)
struct uwsgi_app *ua = NULL;
@@ -586,7 +684,7 @@ static void vacuum(void) {
uwsgi_error("chdir()");
}
}
while(uwsgi_sock) {
while (uwsgi_sock) {
if (uwsgi_sock->family == AF_UNIX) {
if (unlink(uwsgi_sock->name)) {
uwsgi_error("unlink()");
@@ -676,6 +774,7 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi.signal_socket = -1;
uwsgi.emperor_fd_config = -1;
uwsgi.emperor_pid = -1;
uwsgi.cluster_fd = -1;
uwsgi.cores = 1;
@@ -703,6 +802,14 @@ int main(int argc, char *argv[], char *envp[]) {
uwsgi.rl.rlim_cur = 0;
uwsgi.rl.rlim_max = 0;
// are we under systemd ?
char *notify_socket = getenv("NOTIFY_SOCKET");
if (notify_socket) {
uwsgi_systemd_init(notify_socket);
}
uwsgi_notify("initializing uWSGI");
emperor_env = getenv("UWSGI_EMPEROR_FD");
if (emperor_env) {
uwsgi.has_emperor = 1;
@@ -1105,27 +1212,56 @@ int main(int argc, char *argv[], char *envp[]) {
fclose(pidfile);
}
/*
for (i = 0; i < uwsgi.shared_sockets_cnt; i++) {
char *tcp_port = strchr(uwsgi.shared_sockets[i].name, ':');
struct uwsgi_socket *shared_sock = uwsgi.shared_sockets;
while (shared_sock) {
char *tcp_port = strchr(shared_sock->name, ':');
if (tcp_port == NULL) {
uwsgi.shared_sockets[i].fd = bind_to_unix(uwsgi.shared_sockets[i].name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
uwsgi.shared_sockets[i].family = AF_UNIX;
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", i, uwsgi.shared_sockets[i].name, uwsgi.shared_sockets[i].fd);
shared_sock->fd = bind_to_unix(shared_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
shared_sock->family = AF_UNIX;
uwsgi_log("uwsgi shared socket %d bound to UNIX address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
}
else {
uwsgi.shared_sockets[i].fd = bind_to_tcp(uwsgi.shared_sockets[i].name, uwsgi.listen_queue, tcp_port);
uwsgi.shared_sockets[i].family = AF_INET;
uwsgi_log("uwsgi shared socket %d bound to TCP address %s fd %d\n", i, uwsgi.shared_sockets[i].name, uwsgi.shared_sockets[i].fd);
shared_sock->fd = bind_to_tcp(shared_sock->name, uwsgi.listen_queue, tcp_port);
shared_sock->family = AF_INET;
uwsgi_log("uwsgi shared socket %d bound to TCP address %s fd %d\n", uwsgi_get_shared_socket_num(shared_sock), shared_sock->name, shared_sock->fd);
}
if (uwsgi.shared_sockets[i].fd < 0) {
uwsgi_log("unable to create shared socket on: %s\n", uwsgi.shared_sockets[i].name);
if (shared_sock->fd < 0) {
uwsgi_log("unable to create shared socket on: %s\n", shared_sock->name);
exit(1);
}
uwsgi.shared_sockets[i].bound = 1;
shared_sock->bound = 1;
shared_sock = shared_sock->next;
}
*/
// start the Emperor if needed
if (uwsgi.early_emperor && uwsgi.emperor_dir) {
if (!uwsgi.sockets && !uwsgi.gateways_cnt && !uwsgi.master_process) {
uwsgi_notify_ready();
emperor_loop();
// never here
exit(1);
}
uwsgi.emperor_pid = fork();
if (uwsgi.emperor_pid < 0) {
uwsgi_error("pid()");
exit(1);
}
else if (uwsgi.emperor_pid == 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
emperor_loop();
// never here
exit(1);
}
}
// call jail systems
for (i = 0; i < uwsgi.gp_cnt; i++) {
@@ -1163,17 +1299,17 @@ int uwsgi_start(void *v_argv) {
#endif
pid_t pid;
int i, j;
union uwsgi_sockaddr usa;
union uwsgi_sockaddr_ptr gsa;
socklen_t socket_type_len;
int emperor_pipe[2];
struct uwsgi_socket *uwsgi_sock;
#ifdef __linux__
uwsgi_set_cgroup();
if (uwsgi.ns) {
linux_namespace_jail();
}
@@ -1254,10 +1390,12 @@ int uwsgi_start(void *v_argv) {
// start the Emperor if needed
if (uwsgi.emperor_dir) {
if (!uwsgi.early_emperor && uwsgi.emperor_dir) {
if (socketpair(AF_UNIX, SOCK_STREAM, 0, emperor_pipe)) {
uwsgi_error("socketpair()");
if (!uwsgi.sockets && !uwsgi.gateways_cnt && !uwsgi.master_process) {
uwsgi_notify_ready();
emperor_loop();
// never here
exit(1);
}
@@ -1266,22 +1404,16 @@ int uwsgi_start(void *v_argv) {
uwsgi_error("pid()");
exit(1);
}
else if (uwsgi.emperor_pid > 0) {
close(emperor_pipe[1]);
else if (uwsgi.emperor_pid == 0) {
#ifdef __linux__
if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
uwsgi_error("prctl()");
}
#endif
emperor_loop();
// never here
exit(1);
}
// do not go on if no socket or gateway is defined
if (!uwsgi.sockets && !uwsgi.gateways_cnt) {
exit(0);
}
close(emperor_pipe[0]);
uwsgi.has_emperor = 1;
uwsgi.emperor_fd = emperor_pipe[1];
uwsgi.master_process = 1;
uwsgi.no_orphans = 1;
}
@@ -1455,7 +1587,7 @@ int uwsgi_start(void *v_argv) {
//check for inherited sockets
if (uwsgi.is_a_reload) {
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
while (uwsgi_sock) {
//a bit overengineering
if (uwsgi_sock->name[0] != 0) {
for (j = 3; j < sysconf(_SC_OPEN_MAX); j++) {
@@ -1480,7 +1612,7 @@ int uwsgi_start(void *v_argv) {
gsa.sa = (struct sockaddr *) &usa;
if (!getsockname(j, gsa.sa, &socket_type_len)) {
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
while (uwsgi_sock) {
if (uwsgi_sock->fd == j && uwsgi_sock->bound) {
useless = 0;
break;
@@ -1494,7 +1626,7 @@ int uwsgi_start(void *v_argv) {
}
//now bind all the unbound sockets
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
while (uwsgi_sock) {
if (!uwsgi_sock->bound) {
char *tcp_port = strchr(uwsgi_sock->name, ':');
if (tcp_port == NULL) {
@@ -1519,7 +1651,7 @@ int uwsgi_start(void *v_argv) {
int zero_used = 0;
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
while (uwsgi_sock) {
if (uwsgi_sock->bound && uwsgi_sock->fd == 0) {
zero_used = 1;
break;
@@ -1531,14 +1663,13 @@ int uwsgi_start(void *v_argv) {
socket_type_len = sizeof(struct sockaddr_un);
gsa.sa = (struct sockaddr *) &usa;
if (!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_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
else {
uwsgi_sock = uwsgi_new_socket(":0");
uwsgi_log("uwsgi socket %d inherited INET address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
if (gsa.sa->sa_family == AF_UNIX) {
uwsgi_sock = uwsgi_new_socket(usa.sa_un.sun_path);
uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
else {
uwsgi_sock = uwsgi_new_socket(":0");
uwsgi_log("uwsgi socket %d inherited INET address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
}
}
else {
@@ -1560,7 +1691,7 @@ int uwsgi_start(void *v_argv) {
// put listening socket in non-blocking state and set the protocol
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
while (uwsgi_sock) {
uwsgi_sock->arg = fcntl(uwsgi_sock->fd, F_GETFL, NULL);
if (uwsgi_sock->arg < 0) {
uwsgi_error("fcntl()");
@@ -1623,10 +1754,11 @@ int uwsgi_start(void *v_argv) {
}
#endif
}
// initialize request plugin only if workers or master are available
if (uwsgi.sockets || uwsgi.master_process) {
if (uwsgi.sockets || uwsgi.master_process || uwsgi.no_server) {
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init) {
uwsgi.p[i]->init();
@@ -1664,7 +1796,7 @@ int uwsgi_start(void *v_argv) {
}
#endif
if (!uwsgi.sockets && !uwsgi.gateways_cnt && !uwsgi.no_server && !uwsgi.udp_socket) {
if (!uwsgi.sockets && !uwsgi.gateways_cnt && !uwsgi.no_server && !uwsgi.udp_socket && !uwsgi.emperor_dir) {
uwsgi_log("The -s/--socket option is missing and stdin is not a socket.\n");
exit(1);
}
@@ -1677,7 +1809,7 @@ int uwsgi_start(void *v_argv) {
#ifdef UWSGI_DEBUG
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
while (uwsgi_sock) {
so_bufsize_len = sizeof(int);
if (getsockopt(uwsgi_sock->fd, SOL_SOCKET, SO_RCVBUF, &so_bufsize, &so_bufsize_len)) {
uwsgi_error("getsockopt()");
@@ -1776,7 +1908,7 @@ int uwsgi_start(void *v_argv) {
uwsgi_log("no-server mode requested. Goodbye.\n");
exit(0);
}
//is this a proxy only worker ?
if (!uwsgi.master_process && uwsgi.numproc == 0) {
exit(0);
@@ -1840,25 +1972,15 @@ int uwsgi_start(void *v_argv) {
}
}
for (i = 2 - uwsgi.master_process; i < uwsgi.numproc + 1; i++) {
pid = fork();
if (pid == 0) {
close(uwsgi.shared->worker_signal_pipe[0]);
uwsgi.mypid = getpid();
uwsgi.workers[i].pid = uwsgi.mypid;
uwsgi.workers[i].id = i;
uwsgi.workers[i].last_spawn = time(NULL);
uwsgi.workers[i].manage_next_request = 1;
uwsgi.mywid = i;
break;
}
else if (pid < 1) {
uwsgi_error("fork()");
exit(1);
}
else {
uwsgi_log("spawned uWSGI worker %d (pid: %d, cores: %d)\n", i, pid, uwsgi.cores);
//close(uwsgi.workers[i].pipe[1]);
// uWSGI is ready
uwsgi_notify_ready();
uwsgi.current_time = time(NULL);
if (!uwsgi.cheap) {
for (i = 2 - uwsgi.master_process; i < uwsgi.numproc + 1; i++) {
if (uwsgi_respawn_worker(i))
break;
gettimeofday(&last_respawn, NULL);
uwsgi.respawn_delta = last_respawn.tv_sec;
}
@@ -1871,58 +1993,58 @@ int uwsgi_start(void *v_argv) {
}
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
struct uwsgi_string_list *usl = uwsgi.map_socket;
while (uwsgi_sock) {
struct uwsgi_string_list *usl = uwsgi.map_socket;
int enabled = 1;
while(usl) {
while (usl) {
char *colon = strchr(usl->value, ':');
if (uwsgi_str_num(usl->value, colon-usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
char *colon = strchr(usl->value, ':');
if (uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
enabled = 0;
char *p = strtok(colon+1, ",");
while (p != NULL) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
exit(1);
}
char *p = strtok(colon + 1, ",");
while (p != NULL) {
int w = atoi(p);
if (w < 1 || w > uwsgi.numproc) {
uwsgi_log("invalid worker num: %d\n", w);
exit(1);
}
if (w == uwsgi.mywid) {
enabled = 1;
uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
break;
}
p = strtok(NULL, ",");
}
p = strtok(NULL, ",");
}
}
usl = usl->next;
}
usl = usl->next;
}
if (!enabled) {
int fd = uwsgi_sock->fd;
close(fd);
fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != uwsgi_sock->fd) {
if (dup2(fd, uwsgi_sock->fd)) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
fd = open("/dev/null", O_RDONLY);
if (fd < 0) {
uwsgi_error_open("/dev/null");
exit(1);
}
if (fd != uwsgi_sock->fd) {
if (dup2(fd, uwsgi_sock->fd)) {
uwsgi_error("dup2()");
exit(1);
}
close(fd);
}
uwsgi_sock->disabled = 1;
}
uwsgi_sock = uwsgi_sock->next;
}
}
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
while (uwsgi_sock) {
if (uwsgi_sock->disabled) {
uwsgi_sock = uwsgi_del_socket(uwsgi_sock);
}
@@ -1978,9 +2100,9 @@ int uwsgi_start(void *v_argv) {
}
uwsgi.core = uwsgi_malloc(sizeof(struct uwsgi_core *) * uwsgi.cores);
for (j = 0; j < uwsgi.cores; j++) {
uwsgi.core[j] = uwsgi_malloc(sizeof(struct uwsgi_core));
memset(uwsgi.core[j], 0, sizeof(struct uwsgi_core));
for (j = 0; j < uwsgi.cores; j++) {
uwsgi.core[j] = uwsgi_malloc(sizeof(struct uwsgi_core));
memset(uwsgi.core[j], 0, sizeof(struct uwsgi_core));
}
if (uwsgi.master_as_root) {
@@ -2083,11 +2205,7 @@ int uwsgi_start(void *v_argv) {
exit(1);
}
uwsgi_sock = uwsgi.sockets;
while(uwsgi_sock) {
event_queue_add_fd_read(uwsgi.async_queue, uwsgi_sock->fd);
uwsgi_sock = uwsgi_sock->next;
}
uwsgi_add_sockets_to_queue(uwsgi.async_queue);
}
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
@@ -2115,6 +2233,10 @@ int uwsgi_start(void *v_argv) {
uwsgi_unix_signal(SIGINT, end_me);
uwsgi_unix_signal(SIGTERM, end_me);
if (uwsgi.auto_snapshot) {
uwsgi_unix_signal(SIGURG, snapshot_me);
}
uwsgi_unix_signal(SIGUSR1, stats);
@@ -2127,10 +2249,10 @@ int uwsgi_start(void *v_argv) {
// run fixup handler
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->fixup) {
uwsgi.p[i]->fixup();
}
}
if (uwsgi.p[i]->fixup) {
uwsgi.p[i]->fixup();
}
}
if (uwsgi.chdir2) {
if (chdir(uwsgi.chdir2)) {
@@ -2190,6 +2312,27 @@ int uwsgi_start(void *v_argv) {
}
#endif
uwsgi_ignition();
// never here
exit(0);
}
void uwsgi_ignition() {
int i;
// snapshot workers do not enter the loop until a specific signal (SIGURG) is raised...
if (uwsgi.snapshot) {
wait_for_call_of_duty:
uwsgi_sig_pause();
if (uwsgi.snapshot)
goto wait_for_call_of_duty;
uwsgi_log("[snapshot] process %d is the new worker %d\n", (int) getpid(), uwsgi.mywid);
}
if (uwsgi.loop) {
void (*u_loop) (void) = uwsgi_get_loop(uwsgi.loop);
uwsgi_log("running %s loop %p\n", uwsgi.loop, u_loop);
@@ -2238,8 +2381,11 @@ int uwsgi_start(void *v_argv) {
}
if (uwsgi.snapshot) {
uwsgi_ignition();
}
// never here
return 0;
pthread_exit(NULL);
}
static int manage_base_opt(int i, char *optarg) {
@@ -2297,6 +2443,9 @@ static int manage_base_opt(int i, char *optarg) {
}
build_options();
return 1;
case LONG_ARGS_IDLE:
uwsgi.idle = atoi(optarg);
return 1;
case LONG_ARGS_CHDIR:
uwsgi.chdir = optarg;
return 1;
@@ -2353,9 +2502,22 @@ static int manage_base_opt(int i, char *optarg) {
case LONG_ARGS_RELOAD_MERCY:
uwsgi.reload_mercy = atoi(optarg);
return 1;
case LONG_ARGS_AUTO_SNAPSHOT:
uwsgi.auto_snapshot = -1;
if (optarg) {
uwsgi.auto_snapshot = atoi(optarg);
}
uwsgi.lazy = 1;
return 1;
case LONG_ARGS_LOG_MASTER:
uwsgi.log_master = 1;
return 1;
case LONG_ARGS_LOG_SOCKET:
uwsgi.log_socket = 1;
uwsgi.log_master = 1;
uwsgi.master_process = 1;
log_socket(optarg);
return 1;
case LONG_ARGS_LOG_SYSLOG:
log_syslog(optarg);
uwsgi.log_syslog = 1;
@@ -2363,12 +2525,12 @@ static int manage_base_opt(int i, char *optarg) {
uwsgi.master_process = 1;
return 1;
#ifdef UWSGI_ZEROMQ
case LONG_ARGS_LOG_ZEROMQ:
log_zeromq(optarg);
uwsgi.log_master = 1;
uwsgi.master_process = 1;
return 1;
#endif
case LONG_ARGS_LOG_ZEROMQ:
log_zeromq(optarg);
uwsgi.log_master = 1;
uwsgi.master_process = 1;
return 1;
#endif
case LONG_ARGS_PRINT:
uwsgi_log("%s\n", optarg);
return 1;
@@ -2441,6 +2603,9 @@ static int manage_base_opt(int i, char *optarg) {
uwsgi.erlang_cookie = optarg;
return 1;
#endif
case LONG_ARGS_ADD_HEADER:
uwsgi_string_new_list(&uwsgi.additional_headers, optarg);
return 1;
case LONG_ARGS_CHECK_STATIC:
uwsgi.check_static = realpath(optarg, NULL);
uwsgi.check_static_len = strlen(uwsgi.check_static);
@@ -2725,15 +2890,7 @@ static int manage_base_opt(int i, char *optarg) {
uwsgi_new_socket(generate_socket_name(optarg));
return 1;
case LONG_ARGS_SHARED_SOCKET:
/*
if (uwsgi.shared_sockets_cnt < MAX_SOCKETS) {
uwsgi.shared_sockets[uwsgi.shared_sockets_cnt].name = generate_socket_name(optarg);
uwsgi.shared_sockets_cnt++;
}
else {
uwsgi_log("you can specify at most 8 --socket options\n");
}
*/
uwsgi_new_shared_socket(generate_socket_name(optarg));
return 1;
#ifdef UWSGI_XML
case 'x':
@@ -3599,48 +3756,49 @@ void uwsgi_init_all_apps() {
int i, j;
for (i = 0; i < 0xFF; i++) {
if (uwsgi.p[i]->init_apps) {
uwsgi.p[i]->init_apps();
}
}
if (uwsgi.p[i]->init_apps) {
uwsgi.p[i]->init_apps();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->init_apps) {
uwsgi.gp[i]->init_apps();
}
}
for (i = 0; i < uwsgi.gp_cnt; i++) {
if (uwsgi.gp[i]->init_apps) {
uwsgi.gp[i]->init_apps();
}
}
/*parse xml for <app> tags */
/*parse xml for <app> tags */
#ifdef UWSGI_XML
if (uwsgi.xml_round2 && uwsgi.xml_config != NULL) {
uwsgi_xml_config(uwsgi.xml_config, uwsgi.wsgi_req, 1, NULL);
}
if (uwsgi.xml_round2 && uwsgi.xml_config != NULL) {
uwsgi_xml_config(uwsgi.xml_config, uwsgi.wsgi_req, 1, NULL);
}
#endif
for (i = 0; i < uwsgi.mounts_cnt; i++) {
char *what = strchr(uwsgi.mounts[i], '=');
if (what) {
what[0] = 0;
what++;
uwsgi_log("mounting %s on %s\n", what, uwsgi.mounts[i]);
for (j = 0; j < 0xFF; j++) {
if (uwsgi.p[j]->mount_app) {
if (uwsgi.p[j]->mount_app(uwsgi.mounts[i], what) != -1)
break;
}
}
what--;
what[0] = '=';
}
else {
uwsgi_log("invalid mountpoint: %s\n", uwsgi.mounts[i]);
exit(1);
}
}
for (i = 0; i < uwsgi.mounts_cnt; i++) {
char *what = strchr(uwsgi.mounts[i], '=');
if (what) {
what[0] = 0;
what++;
uwsgi_log("mounting %s on %s\n", what, uwsgi.mounts[i]);
for (j = 0; j < 0xFF; j++) {
if (uwsgi.p[j]->mount_app) {
if (uwsgi.p[j]->mount_app(uwsgi.mounts[i], what) != -1)
break;
}
}
what--;
what[0] = '=';
}
else {
uwsgi_log("invalid mountpoint: %s\n", uwsgi.mounts[i]);
exit(1);
}
}
// no app initialized and virtualhosting enabled
if (uwsgi.apps_cnt == 0 && uwsgi.vhost) {
uwsgi.apps_cnt = 1;
}
// no app initialized and virtualhosting enabled
if (uwsgi.apps_cnt == 0) {
uwsgi_log("*** no app loaded. going in full dynamic mode ***\n");
uwsgi.apps_cnt = 1;
}
}
+76 -7
View File
@@ -2,8 +2,6 @@
/* indent -i8 -br -brs -brf -l0 -npsl -nip -npcs -npsl -di1 */
#define UWSGI_VERSION "0.9.8-dev"
#define UMAX16 65536
#define uwsgi_error(x) uwsgi_log("%s: %s [%s line %d]\n", x, strerror(errno), __FILE__, __LINE__);
@@ -12,6 +10,9 @@
#define uwsgi_debug(x, ...) uwsgi_log("[uWSGI DEBUG] " x, __VA_ARGS__);
#define uwsgi_rawlog(x) if (write(2, x, strlen(x)) != strlen(x)) uwsgi_error("write()")
#define uwsgi_notify(x) if (uwsgi.notify) uwsgi.notify(x)
#define uwsgi_notify_ready() if (uwsgi.notify_ready) uwsgi.notify_ready()
#define wsgi_req_time ((wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec) - (wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec))/1000
#define ushared uwsgi.shared
@@ -93,7 +94,9 @@
#include <syslog.h>
#ifdef UWSGI_HAS_IFADDRS
#include <ifaddrs.h>
#endif
#include <dirent.h>
@@ -246,6 +249,7 @@ struct uwsgi_static_map {
struct uwsgi_string_list {
char *value;
size_t len;
struct uwsgi_string_list *next;
};
@@ -429,6 +433,10 @@ struct uwsgi_opt {
#define LONG_ARGS_LOG_ZEROMQ 17104
#define LONG_ARGS_PROFILER 17105
#define LONG_ARGS_SQLITE3 17106
#define LONG_ARGS_AUTO_SNAPSHOT 17107
#define LONG_ARGS_LOG_SOCKET 17108
#define LONG_ARGS_ADD_HEADER 17109
#define LONG_ARGS_IDLE 17120
#define UWSGI_OK 0
@@ -465,6 +473,8 @@ struct uwsgi_opt {
#define UWSGI_OPTION_LOG_5xx 12
#define UWSGI_OPTION_LOG_BIG 13
#define UWSGI_OPTION_LOG_SENDFILE 14
#define UWSGI_OPTION_BACKLOG_STATUS 15
#define UWSGI_OPTION_BACKLOG_ERRORS 16
#define UWSGI_MODIFIER_ADMIN_REQUEST 10
#define UWSGI_MODIFIER_SPOOL_REQUEST 17
@@ -661,8 +671,10 @@ struct wsgi_request {
struct msghdr msg;
union {
struct cmsghdr cmsg;
#ifndef __NetBSD__
char control [CMSG_SPACE (sizeof (int))];
} msg_control;
#endif
} msg_control;
struct timeval start_of_request;
struct timeval end_of_request;
@@ -830,14 +842,27 @@ struct uwsgi_server {
int autoload;
int snapshot;
int auto_snapshot;
pid_t restore_snapshot;
int respawn_workers;
unsigned int reloads;
int master_as_root;
int die_on_term;
int no_fd_passing;
time_t current_time;
uint64_t master_cycles;
int lazy;
int cheap;
int idle;
int has_emperor;
int emperor_fd;
int emperor_fd_config;
int early_emperor;
char *emperor_dir;
pid_t emperor_pid;
struct uwsgi_config_template *vassals_templates;
@@ -847,6 +872,8 @@ struct uwsgi_server {
char *emperor_amqp_username;
char *emperor_amqp_password;
struct uwsgi_string_list *additional_headers;
time_t master_mercy;
int cpu_affinity;
@@ -888,6 +915,12 @@ struct uwsgi_server {
int log_master;
int log_syslog;
int log_socket;
int log_socket_fd;
union uwsgi_sockaddr *log_socket_addr;
socklen_t log_socket_size;
char *check_static;
size_t check_static_len;
int file_serve_mode;
@@ -1101,9 +1134,6 @@ struct uwsgi_server {
void *zmq_log_socket;
#endif
struct uwsgi_socket *sockets;
// leave a slot for no-orphan mode
int shared_sockets_cnt;
struct uwsgi_socket *shared_sockets;
struct uwsgi_string_list *map_socket;
@@ -1125,6 +1155,11 @@ struct uwsgi_server {
struct wsgi_request *(*current_wsgi_req) (void);
void (*notify) (char *);
void (*notify_ready) (void);
int notification_fd;
void *notification_object;
// usedby suspend/resume loops
void (*schedule_to_main) (struct wsgi_request *);
void (*schedule_to_req) (void);
@@ -1279,7 +1314,7 @@ struct uwsgi_shared {
//vga 80 x25 specific !
char warning_message[81];
uint32_t options[0xFF];
uint32_t options[256];
struct uwsgi_cluster_node nodes[MAX_CLUSTER_NODES];
@@ -1354,9 +1389,17 @@ struct uwsgi_core {
int in_request;
};
struct uwsgi_snapshot {
char *name;
pid_t pid;
time_t timestamp;
};
struct uwsgi_worker {
int id;
pid_t pid;
pid_t snapshot;
uint64_t status;
time_t last_spawn;
@@ -1922,6 +1965,7 @@ char *uwsgi_netstring(char *, size_t, char **, size_t *);
int uwsgi_get_socket_num(struct uwsgi_socket *);
struct uwsgi_socket *uwsgi_new_socket(char *);
struct uwsgi_socket *uwsgi_new_shared_socket(char *);
struct uwsgi_socket *uwsgi_del_socket(struct uwsgi_socket *);
void uwsgi_close_all_sockets(void);
@@ -1934,3 +1978,28 @@ void uwsgi_init_all_apps(void);
void uwsgi_socket_nb(int);
void uwsgi_destroy_request(struct wsgi_request *);
void uwsgi_systemd_init(char *);
void uwsgi_sig_pause(void);
void uwsgi_ignition(void);
void master_check_cluster_nodes(void);
int uwsgi_respawn_worker(int);
void log_socket(char *);
socklen_t socket_to_in_addr(char *, char *, struct sockaddr_in *);
socklen_t socket_to_un_addr(char *, struct sockaddr_un *);
int uwsgi_get_shared_socket_fd_by_num(int);
int uwsgi_get_shared_socket_num(struct uwsgi_socket *);
#ifdef __linux__
void uwsgi_set_cgroup(void);
#endif
void uwsgi_add_sockets_to_queue(int);
void uwsgi_del_sockets_from_queue(int);
+52 -1
View File
@@ -1,5 +1,7 @@
# uWSGI build system
uwsgi_version = '0.9.8'
import os
import re
import time
@@ -23,6 +25,8 @@ GCC = os.environ.get('CC', sysconfig.get_config_var('CC'))
if not GCC:
GCC = 'gcc'
def spcall(cmd):
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,stderr=open('/dev/null','w'))
@@ -34,6 +38,12 @@ def spcall(cmd):
else:
return None
if uwsgi_version.endswith('-dev') and os.path.exists('%s/.hg' % os.path.dirname(os.path.abspath( __file__ ))):
try:
uwsgi_version += spcall('hg tip --template "-{rev}"')
except:
pass
def spcall2(cmd):
p = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE)
@@ -156,7 +166,7 @@ class uConf(object):
self.config = ConfigParser.ConfigParser()
print("using profile: %s" % filename)
self.config.read(filename)
self.gcc_list = ['utils', 'protocol', 'socket', 'logging', 'master', 'emperor',
self.gcc_list = ['utils', 'protocol', 'socket', 'logging', 'master', 'master_utils', 'emperor', 'notify',
'plugins', 'lock', 'cache', 'queue', 'event', 'signal', 'rpc', 'gateway', 'loop', 'lib/rbtree', 'lib/amqp', 'rb_timers', 'uwsgi']
# add protocols
self.gcc_list.append('proto/base')
@@ -227,12 +237,18 @@ class uConf(object):
def get_gcll(self):
global uwsgi_version
self.cflags.append('-DUWSGI_BUILD_DATE="\\"%s\\""' % time.strftime("%d %B %Y %H:%M:%S"))
kvm_list = ['FreeBSD', 'OpenBSD', 'NetBSD', 'DragonFly']
if os.path.exists('/usr/include/ifaddrs.h') or os.path.exists('/usr/local/include/ifaddrs.h'):
self.cflags.append('-DUWSGI_HAS_IFADDRS')
if uwsgi_os == 'SunOS':
self.libs.append('-lsendfile')
self.gcc_list.append('lib/sun_fixes')
self.ldflags.append('-L/lib')
if not uwsgi_os_v.startswith('Nexenta'):
self.libs.remove('-rdynamic')
@@ -394,6 +410,41 @@ class uConf(object):
if os.path.exists('/usr/lib/libuuid.so') or os.path.exists('/usr/local/lib/libuuid.so'):
self.libs.append('-luuid')
if self.get('append_version'):
if not self.get('append_version').startswith('-'):
uwsgi_version += '-'
uwsgi_version += self.get('append_version')
self.cflags.append('-DUWSGI_VERSION="\\"' + uwsgi_version + '\\""')
uver_whole = uwsgi_version.split('-', 1)
if len(uver_whole) == 1:
uver_custom = ''
else:
uver_custom = uver_whole[1]
uver_dots = uver_whole[0].split('.')
uver_base = uver_dots[0]
uver_maj = uver_dots[1]
uver_min = '0'
uver_rev = '0'
if len(uver_dots) > 2:
uver_min = uver_dots[2]
if len(uver_dots) > 3:
uver_rev = uver_dots[3]
self.cflags.append('-DUWSGI_VERSION_BASE="' + uver_base + '"')
self.cflags.append('-DUWSGI_VERSION_MAJOR="' + uver_maj + '"')
self.cflags.append('-DUWSGI_VERSION_MINOR="' + uver_min + '"')
self.cflags.append('-DUWSGI_VERSION_REVISION="' + uver_rev + '"')
self.cflags.append('-DUWSGI_VERSION_CUSTOM="\\"' + uver_custom + '\\""')
if self.get('async'):
self.cflags.append("-DUWSGI_ASYNC")
self.gcc_list.append('async')
+6
View File
@@ -0,0 +1,6 @@
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
+6
View File
@@ -0,0 +1,6 @@
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World! app2 !!!"
+6
View File
@@ -0,0 +1,6 @@
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World! app3"
+6
View File
@@ -0,0 +1,6 @@
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World! app4"
+6
View File
@@ -0,0 +1,6 @@
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World! app5"
+49
View File
@@ -0,0 +1,49 @@
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
gzip on;
upstream uwsgi_server {
server 127.0.0.1:3031;
}
include uwsgi_params;
uwsgi_param UWSGI_FILE $app;
uwsgi_param UWSGI_PYHOME $virtualenv;
server {
listen 8026;
server_name flask001;
set $app vhosttest/flask001/app1.py;
set $virtualenv vhosttest/venv001;
location / {
uwsgi_pass uwsgi_server;
}
}
server {
listen 8026;
server_name flask002;
set $app vhosttest/flask002/app2.py;
set $virtualenv vhosttest/venv001;
location / {
uwsgi_pass uwsgi_server;
}
}
}
+48
View File
@@ -0,0 +1,48 @@
import uwsgi
def serve_logo(e, sr):
sr('200 OK', [('Content-Type', 'image/png')])
return uwsgi.sendfile('logo_uWSGI.png')
def serve_options(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in xrange(0,256):
yield "%d = %d<br/>" % (opt, uwsgi.get_option(opt))
def serve_config(e, sr):
sr('200 OK', [('Content-Type', 'text/html')])
for opt in uwsgi.opt.keys():
yield "%s = %s<br/>" % (opt, uwsgi.opt[opt])
routes = {}
routes['/logo'] = serve_logo
routes['/config'] = serve_config
routes['/options'] = serve_options
def application(env, start_response):
if routes.has_key(env['PATH_INFO']):
return routes[env['PATH_INFO']](env, start_response)
start_response('200 OK', [('Content-Type', 'text/html')])
return """
<img src="/logo"/> version %s<br/>
<hr size="1"/>
Configuration<br/>
<iframe src="/config"></iframe><br/>
<br/>
Dynamic options<br/>
<iframe src="/options"></iframe><br/>
""" % (uwsgi.version)
+1 -1
View File
@@ -4,7 +4,7 @@
"workers": 8,
"module": "werkzeug.testapp:test_app",
"master": true,
"socket": [ "/tmp/uwsgi.sock", "127.0.0.1:3031" ],
"socket": [ "/tmp/uwsgi.sock", "127.0.0.1:3031", "@foobar" ],
"pythonpath": [ "/foo", "/bar" ],
"show-config": true
}