mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-06 05:31:44 +00:00
Merge branch 'master' of https://github.com/unbit/uwsgi
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
surprise i am empty !
|
||||
The uWSGI project
|
||||
|
||||
Look in the online documentation on https://uwsgi-docs.readthedocs.org/en/latest/
|
||||
For official documentation check: https://uwsgi-docs.readthedocs.org/en/latest/
|
||||
|
||||
For commercial support check: http://unbit.com/
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
xml = auto
|
||||
yaml = true
|
||||
json = auto
|
||||
zeromq = auto
|
||||
ssl = auto
|
||||
pcre = auto
|
||||
routing = auto
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
xml = false
|
||||
yaml = false
|
||||
json = false
|
||||
zeromq = false
|
||||
ssl = false
|
||||
pcre = false
|
||||
routing = false
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
xml = true
|
||||
yaml = true
|
||||
json = true
|
||||
zeromq = true
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
xml = true
|
||||
yaml = true
|
||||
json = false
|
||||
zeromq = false
|
||||
ssl = true
|
||||
pcre = true
|
||||
routing = true
|
||||
|
||||
+64
-20
@@ -4,18 +4,18 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is a general purpose async loop engine (it expects a coroutine based approach)
|
||||
This is a general-purpose async loop engine (it expects a coroutine-based approach)
|
||||
|
||||
You can see it as an hub holding the following structures:
|
||||
|
||||
1) the runqueue, cores ready to be run are appended in this list
|
||||
1) the runqueue, cores ready to be run are appended to this list
|
||||
|
||||
2) the fd list, this is a list of monitored file descriptors, a core can wait for all the file descriptors it needs
|
||||
|
||||
3) the timeout value, if set the current core will timeout aftert he specified number of seconds (unless an event cancel it)
|
||||
3) the timeout value, if set, the current core will timeout after the specified number of seconds (unless an event cancels it)
|
||||
|
||||
|
||||
IMPORTANT: this is not a callback based engine !!!
|
||||
IMPORTANT: this is not a callback-based engine !!!
|
||||
|
||||
*/
|
||||
|
||||
@@ -28,7 +28,6 @@ void uwsgi_async_queue_is_full(time_t now) {
|
||||
}
|
||||
|
||||
void uwsgi_async_init() {
|
||||
int i;
|
||||
|
||||
uwsgi.async_queue = event_queue_init();
|
||||
|
||||
@@ -40,16 +39,9 @@ void uwsgi_async_init() {
|
||||
|
||||
uwsgi.rb_async_timeouts = uwsgi_init_rb_timer();
|
||||
|
||||
// a stack of unused cores
|
||||
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
|
||||
|
||||
// fill it with default values
|
||||
for (i = 0; i < uwsgi.async; i++) {
|
||||
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
}
|
||||
|
||||
// the first available core is the last one
|
||||
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
|
||||
// optimization, this array maps file descriptor to requests
|
||||
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
|
||||
}
|
||||
|
||||
@@ -159,7 +151,7 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
wsgi_req = (struct wsgi_request *) urbt->data;
|
||||
// timeout expired
|
||||
wsgi_req->async_timed_out = 1;
|
||||
// reset teh request
|
||||
// reset the request
|
||||
async_reset_request(wsgi_req);
|
||||
// push it in the runqueue
|
||||
runqueue_push(wsgi_req);
|
||||
@@ -173,6 +165,11 @@ static void async_expire_timeouts(uint64_t now) {
|
||||
|
||||
int async_add_fd_read(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table){
|
||||
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0)
|
||||
@@ -224,8 +221,47 @@ static int async_wait_fd_read(int fd, int timeout) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int async_wait_fd_read2(int fd0, int fd1, int timeout, int *fd) {
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd0, timeout)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (async_add_fd_read(wsgi_req, fd1, timeout)) {
|
||||
// reset already registered fd
|
||||
async_reset_request(wsgi_req);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(wsgi_req);
|
||||
}
|
||||
|
||||
if (wsgi_req->async_timed_out) {
|
||||
wsgi_req->async_timed_out = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (wsgi_req->async_ready_fd) {
|
||||
*fd = wsgi_req->async_last_ready_fd;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
if (uwsgi.async < 2 || !uwsgi.rb_async_timeouts) {
|
||||
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
wsgi_req->async_ready_fd = 0;
|
||||
|
||||
if (timeout > 0 && wsgi_req->async_timeout == NULL) {
|
||||
@@ -236,6 +272,11 @@ void async_add_timeout(struct wsgi_request *wsgi_req, int timeout) {
|
||||
|
||||
int async_add_fd_write(struct wsgi_request *wsgi_req, int fd, int timeout) {
|
||||
|
||||
if (uwsgi.async < 2 || !uwsgi.async_waiting_fd_table) {
|
||||
uwsgi_log_verbose("ASYNC call without async mode !!!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct uwsgi_async_fd *last_uad = NULL, *uad = wsgi_req->waiting_fds;
|
||||
|
||||
if (fd < 0)
|
||||
@@ -295,9 +336,8 @@ void async_schedule_to_req(void) {
|
||||
// a trick to avoid calling routes again
|
||||
uwsgi.wsgi_req->is_routing = 1;
|
||||
#endif
|
||||
if (uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req) <= UWSGI_OK) {
|
||||
goto end;
|
||||
}
|
||||
uwsgi.wsgi_req->async_status = uwsgi.p[uwsgi.wsgi_req->uh->modifier1]->request(uwsgi.wsgi_req);
|
||||
if (uwsgi.wsgi_req->async_status <= UWSGI_OK) goto end;
|
||||
|
||||
if (uwsgi.schedule_to_main) {
|
||||
uwsgi.schedule_to_main(uwsgi.wsgi_req);
|
||||
@@ -366,10 +406,13 @@ void async_loop() {
|
||||
void *events = event_queue_alloc(64);
|
||||
struct uwsgi_socket *uwsgi_sock;
|
||||
|
||||
uwsgi_async_init();
|
||||
|
||||
uwsgi.async_runqueue = NULL;
|
||||
|
||||
uwsgi.wait_write_hook = async_wait_fd_write;
|
||||
uwsgi.wait_read_hook = async_wait_fd_read;
|
||||
uwsgi.wait_read2_hook = async_wait_fd_read2;
|
||||
|
||||
if (uwsgi.signal_socket > -1) {
|
||||
event_queue_add_fd_read(uwsgi.async_queue, uwsgi.signal_socket);
|
||||
@@ -478,7 +521,8 @@ void async_loop() {
|
||||
// remove fd from event poll and fd proto table
|
||||
uwsgi.async_proto_fd_table[interesting_fd] = NULL;
|
||||
event_queue_del_fd(uwsgi.async_queue, interesting_fd, event_queue_read());
|
||||
// put request in the runqueue
|
||||
// put request in the runqueue (set it as UWSGI_OK to signal the first run)
|
||||
uwsgi.wsgi_req->async_status = UWSGI_OK;
|
||||
runqueue_push(uwsgi.wsgi_req);
|
||||
continue;
|
||||
}
|
||||
|
||||
+1
-1
@@ -762,7 +762,7 @@ int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *v
|
||||
}
|
||||
// mark used blocks;
|
||||
uint64_t needed_blocks = cache_mark_blocks(uc, uci->first_block, vallen);
|
||||
// optimize teh scan
|
||||
// optimize the scan
|
||||
if (uc->blocks_bitmap_pos + (needed_blocks+1) > uc->blocks) {
|
||||
uc->blocks_bitmap_pos = 0;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
int uwsgi_simple_wait_milliseconds_hook(int timeout) {
|
||||
return poll(NULL, 0, timeout);
|
||||
}
|
||||
|
||||
|
||||
// in the future we will need to use the best clock source for each os/system
|
||||
time_t uwsgi_now() {
|
||||
return uwsgi.clock->seconds();
|
||||
|
||||
+5
-4
@@ -720,18 +720,18 @@ char *uwsgi_manage_placeholder(char *key) {
|
||||
}
|
||||
else if (!strcmp(p, "++")) {
|
||||
if (current_value) {
|
||||
int64_t tmp_value = strtoll(current_value, NULL, 10);
|
||||
int64_t tmp_num = strtoll(current_value, NULL, 10);
|
||||
free(current_value);
|
||||
current_value = uwsgi_64bit2str(tmp_value+1);
|
||||
current_value = uwsgi_64bit2str(tmp_num+1);
|
||||
}
|
||||
state = concat;
|
||||
continue;
|
||||
}
|
||||
else if (!strcmp(p, "--")) {
|
||||
if (current_value) {
|
||||
int64_t tmp_value = strtoll(current_value, NULL, 10);
|
||||
int64_t tmp_num = strtoll(current_value, NULL, 10);
|
||||
free(current_value);
|
||||
current_value = uwsgi_64bit2str(tmp_value-1);
|
||||
current_value = uwsgi_64bit2str(tmp_num-1);
|
||||
}
|
||||
state = concat;
|
||||
continue;
|
||||
@@ -795,6 +795,7 @@ char *uwsgi_manage_placeholder(char *key) {
|
||||
// reset state to concat
|
||||
state = concat;
|
||||
}
|
||||
free(tmp_value);
|
||||
|
||||
return current_value;
|
||||
}
|
||||
|
||||
+7
-7
@@ -6,7 +6,7 @@ extern struct uwsgi_server uwsgi;
|
||||
|
||||
External uwsgi daemons
|
||||
|
||||
There are 3 kind of daemons (read: external applications) that can be managed
|
||||
There are 3 kinds of daemons (read: external applications) that can be managed
|
||||
by uWSGI.
|
||||
|
||||
1) dumb daemons (attached with --attach-daemon)
|
||||
@@ -14,12 +14,12 @@ extern struct uwsgi_server uwsgi;
|
||||
and the process is respawned
|
||||
2) smart daemons with daemonization
|
||||
you specify a pidfile and a command
|
||||
- on startup - if the pidfile does not exists or contains a not-available pid (checked with kill(pid, 0))
|
||||
the daemon is respawned
|
||||
- on master ckeck - if the pidfile does not exist or if it point to a non-existent pid
|
||||
the daemon is respawned
|
||||
- on startup - if the pidfile does not exist or contains a non-available pid (checked with kill(pid, 0))
|
||||
the daemon is respawned
|
||||
- on master check - if the pidfile does not exist or if it points to a non-existent pid
|
||||
the daemon is respawned
|
||||
3) smart daemons without daemonization
|
||||
same as 2, but the daemonization and pidfile creation is managed by uWSGI
|
||||
same as 2, but the daemonization and pidfile creation are managed by uWSGI
|
||||
|
||||
status:
|
||||
|
||||
@@ -232,7 +232,7 @@ void uwsgi_detach_daemons() {
|
||||
if (ud->pid > 0 && !ud->pidfile) {
|
||||
#endif
|
||||
uwsgi_log("[uwsgi-daemons] stopping daemon (pid: %d): %s\n", (int) ud->pid, ud->command);
|
||||
// try to gracefully stop daemon, kill it if it won't die
|
||||
// try to stop daemon gracefully, kill it if it won't die
|
||||
// if mercy is not set then wait up to 3 seconds
|
||||
time_t timeout = uwsgi_now() + (uwsgi.reload_mercy ? uwsgi.reload_mercy : 3);
|
||||
int waitpid_status;
|
||||
|
||||
+46
-8
@@ -59,12 +59,12 @@ void uwsgi_emperor_blacklist_add(char *id) {
|
||||
uebi->throttle_level += (uwsgi.emperor_throttle * 1000);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
|
||||
uwsgi_log_verbose("[emperor] maximum throttle level for vassal %s reached !!!\n", id);
|
||||
uebi->throttle_level = uebi->throttle_level / 2;
|
||||
}
|
||||
uebi->attempt++;
|
||||
if (uebi->attempt == 2) {
|
||||
uwsgi_log("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
|
||||
uwsgi_log_verbose("[emperor] unloyal bad behaving vassal found: %s throttling it...\n", id);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -603,7 +603,7 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
uwsgi_log("[emperor] %s stop-hook returned %d\n", c_ui->name, stop_hook_ret);
|
||||
}
|
||||
|
||||
uwsgi_log("[emperor] removed uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log_verbose("[emperor] removed uwsgi instance %s\n", c_ui->name);
|
||||
// put the instance in the blacklist (or update its throttling value)
|
||||
if (!c_ui->loyal) {
|
||||
uwsgi_emperor_blacklist_add(c_ui->name);
|
||||
@@ -632,7 +632,7 @@ void emperor_stop(struct uwsgi_instance *c_ui) {
|
||||
c_ui->status = 1;
|
||||
c_ui->cursed_at = uwsgi_now();
|
||||
|
||||
uwsgi_log("[emperor] stop the uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log_verbose("[emperor] stop the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_curse(struct uwsgi_instance *c_ui) {
|
||||
@@ -642,7 +642,7 @@ void emperor_curse(struct uwsgi_instance *c_ui) {
|
||||
c_ui->status = 1;
|
||||
c_ui->cursed_at = uwsgi_now();
|
||||
|
||||
uwsgi_log("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
|
||||
uwsgi_log_verbose("[emperor] curse the uwsgi instance %s (pid: %d)\n", c_ui->name, (int) c_ui->pid);
|
||||
|
||||
}
|
||||
|
||||
@@ -675,8 +675,12 @@ void emperor_respawn(struct uwsgi_instance *c_ui, time_t mod) {
|
||||
c_ui->respawns++;
|
||||
c_ui->last_mod = mod;
|
||||
c_ui->last_run = uwsgi_now();
|
||||
// reset readyness
|
||||
c_ui->ready = 0;
|
||||
// reset accepting
|
||||
c_ui->accepting = 0;
|
||||
|
||||
uwsgi_log("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
uwsgi_log_verbose("[emperor] reload the uwsgi instance %s\n", c_ui->name);
|
||||
}
|
||||
|
||||
void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, char *config, uint32_t config_size, uid_t uid, gid_t gid, char *socket_name) {
|
||||
@@ -763,6 +767,9 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
n_ui->uid = uid;
|
||||
n_ui->gid = gid;
|
||||
n_ui->last_mod = born;
|
||||
// start non-ready
|
||||
n_ui->last_ready = 0;
|
||||
n_ui->ready = 0;
|
||||
// start without loyalty
|
||||
n_ui->last_loyal = 0;
|
||||
n_ui->loyal = 0;
|
||||
@@ -1552,7 +1559,7 @@ void emperor_loop() {
|
||||
if (byte == 17) {
|
||||
ui_current->loyal = 1;
|
||||
ui_current->last_loyal = uwsgi_now();
|
||||
uwsgi_log("[emperor] vassal %s is now loyal\n", ui_current->name);
|
||||
uwsgi_log_verbose("[emperor] vassal %s is now loyal\n", ui_current->name);
|
||||
// remove it from the blacklist
|
||||
uwsgi_emperor_blacklist_remove(ui_current->name);
|
||||
// TODO post-start hook
|
||||
@@ -1565,12 +1572,22 @@ void emperor_loop() {
|
||||
emperor_stop(ui_current);
|
||||
}
|
||||
else if (byte == 30 && uwsgi.emperor_broodlord > 0 && uwsgi.emperor_broodlord_count < uwsgi.emperor_broodlord) {
|
||||
uwsgi_log("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
uwsgi_log_verbose("[emperor] going in broodlord mode: launching zergs for %s\n", ui_current->name);
|
||||
char *zerg_name = uwsgi_concat3(ui_current->name, ":", "zerg");
|
||||
// here we discard socket name as broodlord/zerg cannot be on demand
|
||||
emperor_add(ui_current->scanner, zerg_name, uwsgi_now(), NULL, 0, ui_current->uid, ui_current->gid, NULL);
|
||||
free(zerg_name);
|
||||
}
|
||||
else if (byte == 5) {
|
||||
ui_current->accepting = 1;
|
||||
ui_current->last_accepting = uwsgi_now();
|
||||
uwsgi_log_verbose("[emperor] vassal %s is ready to accept requests\n", ui_current->name);
|
||||
}
|
||||
else if (byte == 1) {
|
||||
ui_current->ready = 1;
|
||||
ui_current->last_ready = uwsgi_now();
|
||||
uwsgi_log_verbose("[emperor] vassal %s has been spawned\n", ui_current->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -1773,8 +1790,16 @@ void emperor_send_stats(int fd) {
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "loyal", (unsigned long long) c_ui->loyal))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "ready", (unsigned long long) c_ui->ready))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) c_ui->accepting))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_loyal", (unsigned long long) c_ui->last_loyal))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_ready", (unsigned long long) c_ui->last_ready))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_accepting", (unsigned long long) c_ui->last_accepting))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "first_run", (unsigned long long) c_ui->first_run))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "last_run", (unsigned long long) c_ui->last_run))
|
||||
@@ -2105,3 +2130,16 @@ void uwsgi_master_manage_emperor_proxy() {
|
||||
|
||||
close(ep_client);
|
||||
}
|
||||
|
||||
static void emperor_notify_ready() {
|
||||
if (!uwsgi.has_emperor) return;
|
||||
char byte = 1;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("emperor_notify_ready()/write()");
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_setup_emperor() {
|
||||
if (!uwsgi.has_emperor) return;
|
||||
uwsgi.notify_ready = emperor_notify_ready;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,30 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static int error_page(struct wsgi_request *wsgi_req, struct uwsgi_string_list *l) {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, l) {
|
||||
struct stat st;
|
||||
if (!stat(usl->value, &st)) {
|
||||
int fd = open(usl->value, O_RDONLY);
|
||||
if (fd >= 0) {
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/html", 9)) { close(fd); return 0;}
|
||||
if (uwsgi_response_add_content_length(wsgi_req, st.st_size)) { close(fd); return 0;}
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, st.st_size);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// generate internal server error message
|
||||
void uwsgi_500(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "500 Internal Server Error", 25)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_500)) return;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Internal Server Error", 21);
|
||||
}
|
||||
|
||||
@@ -11,6 +32,7 @@ void uwsgi_500(struct wsgi_request *wsgi_req) {
|
||||
void uwsgi_404(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "404 Not Found", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_404)) return;
|
||||
if (uwsgi_response_add_header(wsgi_req, "Content-Type", 12, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Not Found", 9);
|
||||
}
|
||||
@@ -18,6 +40,7 @@ void uwsgi_404(struct wsgi_request *wsgi_req) {
|
||||
void uwsgi_403(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi_response_prepare_headers(wsgi_req, "403 Forbidden", 13)) return;
|
||||
if (uwsgi_response_add_connection_close(wsgi_req)) return;
|
||||
if (error_page(wsgi_req, uwsgi.error_page_403)) return;
|
||||
if (uwsgi_response_add_content_type(wsgi_req, "text/plain", 10)) return;
|
||||
uwsgi_response_write_body_do(wsgi_req, "Forbidden", 9);
|
||||
}
|
||||
|
||||
@@ -1231,6 +1231,8 @@ static int timerfd_create(clockid_t __clock_id, int __flags) {
|
||||
return syscall(283, __clock_id, __flags);
|
||||
#elif defined(__i386__)
|
||||
return syscall(322, __clock_id, __flags);
|
||||
#elif defined(__arm__)
|
||||
return syscall(350, __clock_id, __flags);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
@@ -1241,6 +1243,10 @@ static int timerfd_settime(int __ufd, int __flags, __const struct itimerspec *__
|
||||
return syscall(286, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__i386__)
|
||||
return syscall(325, __ufd, __flags, __utmr, __otmr);
|
||||
#elif defined(__arm__)
|
||||
return syscall(353, __ufd, __flags, __utmr, __otmr);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
+24
-10
@@ -24,16 +24,29 @@ static char *uwsgi_fifo_by_slot() {
|
||||
return uwsgi.master_fifo->value;
|
||||
}
|
||||
|
||||
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; }
|
||||
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; }
|
||||
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; }
|
||||
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; }
|
||||
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; }
|
||||
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; }
|
||||
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; }
|
||||
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; }
|
||||
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; }
|
||||
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; }
|
||||
#define announce_fifo uwsgi_log_verbose("active master fifo is now %s\n", uwsgi_fifo_by_slot())
|
||||
|
||||
static void uwsgi_fifo_set_slot_zero() { uwsgi.master_fifo_slot = 0; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_one() { uwsgi.master_fifo_slot = 1; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_two() { uwsgi.master_fifo_slot = 2; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_three() { uwsgi.master_fifo_slot = 3; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_four() { uwsgi.master_fifo_slot = 4; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_five() { uwsgi.master_fifo_slot = 5; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_six() { uwsgi.master_fifo_slot = 6; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_seven() { uwsgi.master_fifo_slot = 7; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_eight() { uwsgi.master_fifo_slot = 8; announce_fifo; }
|
||||
static void uwsgi_fifo_set_slot_nine() { uwsgi.master_fifo_slot = 9; announce_fifo; }
|
||||
|
||||
static void subscriptions_blocker() {
|
||||
if (uwsgi.subscriptions_blocked) {
|
||||
uwsgi_log_verbose("subscriptions re-enabled\n");
|
||||
uwsgi.subscriptions_blocked = 0;
|
||||
}
|
||||
else {
|
||||
uwsgi.subscriptions_blocked = 1;
|
||||
uwsgi_log_verbose("subscriptions blocked\n");
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -71,6 +84,7 @@ void uwsgi_master_fifo_prepare() {
|
||||
uwsgi_fifo_table['r'] = grace_them_all;
|
||||
uwsgi_fifo_table['R'] = reap_them_all;
|
||||
uwsgi_fifo_table['s'] = stats;
|
||||
uwsgi_fifo_table['S'] = subscriptions_blocker;
|
||||
uwsgi_fifo_table['w'] = uwsgi_reload_workers;
|
||||
uwsgi_fifo_table['W'] = uwsgi_brutally_reload_workers;
|
||||
|
||||
|
||||
@@ -78,6 +78,67 @@ static int uwsgi_hook_print(char *arg) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_unlink(char *arg) {
|
||||
int ret = unlink(arg);
|
||||
if (ret) {
|
||||
uwsgi_error("uwsgi_hook_unlink()/unlink()");
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_writefifo(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook writefifo syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY|O_NONBLOCK);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
if (errno == ENODEV) return 0;
|
||||
#ifdef ENXIO
|
||||
if (errno == ENXIO) return 0;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
if (write(fd, space+1, l) != (ssize_t) l) {
|
||||
uwsgi_error("uwsgi_hook_writefifo()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_hook_write(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid hook write syntax, must be: <file> <string>\n");
|
||||
return -1;
|
||||
}
|
||||
*space = 0;
|
||||
int fd = open(arg, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
uwsgi_error_open(arg);
|
||||
*space = ' ';
|
||||
return -1;
|
||||
}
|
||||
*space = ' ';
|
||||
size_t l = strlen(space+1);
|
||||
if (write(fd, space+1, l) != (ssize_t) l) {
|
||||
uwsgi_error("uwsgi_hook_write()/write()");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int uwsgi_hook_callint(char *arg) {
|
||||
char *space = strchr(arg, ' ');
|
||||
if (space) {
|
||||
@@ -177,6 +238,10 @@ void uwsgi_register_base_hooks() {
|
||||
uwsgi_register_hook("cd", uwsgi_hook_chdir);
|
||||
uwsgi_register_hook("exec", uwsgi_hook_exec);
|
||||
|
||||
uwsgi_register_hook("write", uwsgi_hook_write);
|
||||
uwsgi_register_hook("writefifo", uwsgi_hook_writefifo);
|
||||
uwsgi_register_hook("unlink", uwsgi_hook_unlink);
|
||||
|
||||
uwsgi_register_hook("mount", uwsgi_mount_hook);
|
||||
uwsgi_register_hook("umount", uwsgi_umount_hook);
|
||||
|
||||
|
||||
@@ -170,6 +170,8 @@ void uwsgi_init_default() {
|
||||
|
||||
uwsgi.wait_read_hook = uwsgi_simple_wait_read_hook;
|
||||
uwsgi.wait_write_hook = uwsgi_simple_wait_write_hook;
|
||||
uwsgi.wait_milliseconds_hook = uwsgi_simple_wait_milliseconds_hook;
|
||||
uwsgi.wait_read2_hook = uwsgi_simple_wait_read2_hook;
|
||||
|
||||
uwsgi_websockets_init();
|
||||
|
||||
|
||||
@@ -756,11 +756,12 @@ int uwsgi_write_true_nb(int fd, char *buf, size_t remains, int timeout) {
|
||||
int ret;
|
||||
|
||||
while(remains > 0) {
|
||||
errno = 0;
|
||||
ssize_t len = write(fd, ptr, remains);
|
||||
if (len > 0) goto written;
|
||||
if (len == 0) return -1;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
if (uwsgi_is_again()) goto wait;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
@@ -911,7 +912,7 @@ ssize_t uwsgi_read_true_nb(int fd, char *buf, size_t len, int timeout) {
|
||||
}
|
||||
if (rlen == 0) return -1;
|
||||
if (rlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
if (uwsgi_is_again()) goto wait;
|
||||
}
|
||||
return -1;
|
||||
wait:
|
||||
@@ -961,7 +962,7 @@ int uwsgi_read_with_realloc(int fd, char **buffer, size_t *rlen, int timeout, ui
|
||||
if (len > 0) goto readok;
|
||||
if (len == 0) return -1;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait;
|
||||
if (uwsgi_is_again()) goto wait;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
@@ -1003,7 +1004,7 @@ readok:
|
||||
if (len > 0) goto readok2;
|
||||
if (len == 0) return -1;
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) goto wait2;
|
||||
if (uwsgi_is_again()) goto wait2;
|
||||
return -1;
|
||||
}
|
||||
wait2:
|
||||
|
||||
@@ -647,6 +647,7 @@ void *uwsgi_robust_mutexes_watchdog_loop(void *arg) {
|
||||
for(;;) {
|
||||
uwsgi_lock(uwsgi.the_thunder_lock);
|
||||
uwsgi_unlock(uwsgi.the_thunder_lock);
|
||||
sleep(1);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+53
-43
@@ -211,49 +211,6 @@ void create_logpipe(void) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
// the zeromq logger
|
||||
ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
if (!ul->arg) {
|
||||
uwsgi_log_safe("invalid zeromq syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *ctx = uwsgi_zeromq_init();
|
||||
|
||||
ul->data = zmq_socket(ctx, ZMQ_PUSH);
|
||||
if (ul->data == NULL) {
|
||||
uwsgi_error_safe("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (zmq_connect(ul->data, ul->arg) < 0) {
|
||||
uwsgi_error_safe("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
zmq_msg_t msg;
|
||||
if (zmq_msg_init_size(&msg, len) == 0) {
|
||||
memcpy(zmq_msg_data(&msg), message, len);
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
zmq_sendmsg(ul->data, &msg, 0);
|
||||
#else
|
||||
zmq_send(ul->data, &msg, 0);
|
||||
#endif
|
||||
zmq_msg_close(&msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// log to the specified file or udp address
|
||||
void logto(char *logfile) {
|
||||
|
||||
@@ -618,6 +575,9 @@ void log_request(struct wsgi_request *wsgi_req) {
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_SENDFILE] && wsgi_req->via == UWSGI_VIA_SENDFILE) {
|
||||
goto logit;
|
||||
}
|
||||
if (uwsgi.shared->options[UWSGI_OPTION_LOG_IOERROR] && wsgi_req->read_errors > 0 && wsgi_req->write_errors > 0) {
|
||||
goto logit;
|
||||
}
|
||||
|
||||
if (!log_it)
|
||||
return;
|
||||
@@ -1139,6 +1099,16 @@ static ssize_t uwsgi_lf_ftime(struct wsgi_request * wsgi_req, char **buf) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_tmsecs(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_64bit2str(wsgi_req->start_of_request / (int64_t) 1000);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_tmicros(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_64bit2str(wsgi_req->start_of_request);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_micros(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str(wsgi_req->end_of_request - wsgi_req->start_of_request);
|
||||
return strlen(*buf);
|
||||
@@ -1214,6 +1184,21 @@ static ssize_t uwsgi_lf_headers(struct wsgi_request * wsgi_req, char **buf) {
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_werr(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str((int) wsgi_req->write_errors);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_rerr(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str((int) wsgi_req->read_errors);
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
static ssize_t uwsgi_lf_ioerr(struct wsgi_request * wsgi_req, char **buf) {
|
||||
*buf = uwsgi_num2str((int) (wsgi_req->write_errors + wsgi_req->read_errors));
|
||||
return strlen(*buf);
|
||||
}
|
||||
|
||||
void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
|
||||
struct uwsgi_logchunk *logchunk = uwsgi.logchunks;
|
||||
@@ -1315,6 +1300,16 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
logchunk->func = uwsgi_lf_msecs;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "tmsecs", 6)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_tmsecs;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "tmicros", 7)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_tmicros;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "time", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_time;
|
||||
@@ -1405,6 +1400,21 @@ void uwsgi_add_logchunk(int variable, int pos, char *ptr, size_t len) {
|
||||
logchunk->func = uwsgi_lf_headers;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "werr", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_werr;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "rerr", 4)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_rerr;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_strncmp(ptr, len, "ioerr", 5)) {
|
||||
logchunk->type = 3;
|
||||
logchunk->func = uwsgi_lf_ioerr;
|
||||
logchunk->free = 1;
|
||||
}
|
||||
else if (!uwsgi_starts_with(ptr, len, "metric.", 7)) {
|
||||
logchunk->type = 4;
|
||||
logchunk->ptr = uwsgi_concat2n(ptr+7, len - 7, "", 0);
|
||||
|
||||
@@ -48,6 +48,8 @@ void uwsgi_master_check_chain() {
|
||||
}
|
||||
uwsgi_block_signal(SIGHUP);
|
||||
for(i=1;i<=uwsgi.numproc;i++) {
|
||||
// do not curse a worker until the old one is ready
|
||||
if (uwsgi.workers[i].accepting == 0) break;
|
||||
if (uwsgi.workers[i].pid > 0 && uwsgi.workers[i].cheaped == 0 && uwsgi.workers[i].cursed_at == 0 && i == uwsgi.status.chain_reloading) {
|
||||
uwsgi_curse(i, SIGHUP);
|
||||
break;
|
||||
|
||||
@@ -592,6 +592,8 @@ void uwsgi_fixup_fds(int wid, int muleid, struct uwsgi_gateway *ug) {
|
||||
int uwsgi_respawn_worker(int wid) {
|
||||
|
||||
int respawns = uwsgi.workers[wid].respawn_count;
|
||||
// the workers is not accepting (obviously)
|
||||
uwsgi.workers[wid].accepting = 0;
|
||||
// we count the respawns before errors...
|
||||
uwsgi.workers[wid].respawn_count++;
|
||||
// ... same for update time
|
||||
@@ -990,6 +992,8 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "pid", (unsigned long long) uwsgi.workers[i + 1].pid))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "accepting", (unsigned long long) uwsgi.workers[i + 1].accepting))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "requests", (unsigned long long) uwsgi.workers[i + 1].requests))
|
||||
goto end;
|
||||
if (uwsgi_stats_keylong_comma(us, "delta_requests", (unsigned long long) uwsgi.workers[i + 1].delta_requests))
|
||||
@@ -1129,6 +1133,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
|
||||
if (uwsgi_stats_keylong_comma(us, "write_errors", (unsigned long long) uc->write_errors))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "read_errors", (unsigned long long) uc->read_errors))
|
||||
goto end;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "in_request", (unsigned long long) uc->in_request))
|
||||
goto end;
|
||||
|
||||
|
||||
+43
-1
@@ -752,7 +752,7 @@ void uwsgi_setup_metrics() {
|
||||
uwsgi_metric_name("worker.%d.avg_response_time", i) ; uwsgi_metric_oid("3.%d.8", i);
|
||||
uwsgi_register_metric(buf, buf2, UWSGI_METRIC_GAUGE, "ptr", &uwsgi.workers[i].avg_response_time, 0, NULL);
|
||||
|
||||
uwsgi_metric_name("worker.%d.total_rx", i) ; uwsgi_metric_oid("3.%d.9", i);
|
||||
uwsgi_metric_name("worker.%d.total_tx", i) ; uwsgi_metric_oid("3.%d.9", i);
|
||||
struct uwsgi_metric *tx = uwsgi_register_metric(buf, buf2, UWSGI_METRIC_COUNTER, "ptr", &uwsgi.workers[i].tx, 0, NULL);
|
||||
uwsgi_metric_add_child(total_tx, tx);
|
||||
|
||||
@@ -784,6 +784,9 @@ void uwsgi_setup_metrics() {
|
||||
uwsgi_metric_name2("worker.%d.core.%d.exceptions", i, j) ; uwsgi_metric_oid2("3.%d.2.%d.7", i, j);
|
||||
uwsgi_register_metric(buf, buf2, UWSGI_METRIC_COUNTER, "ptr", &uwsgi.workers[i].cores[j].exceptions, 0, NULL);
|
||||
|
||||
uwsgi_metric_name2("worker.%d.core.%d.read_errors", i, j) ; uwsgi_metric_oid2("3.%d.2.%d.8", i, j);
|
||||
uwsgi_register_metric(buf, buf2, UWSGI_METRIC_COUNTER, "ptr", &uwsgi.workers[i].cores[j].read_errors, 0, NULL);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -970,6 +973,42 @@ static int64_t uwsgi_metric_collector_sum(struct uwsgi_metric *um) {
|
||||
return total;
|
||||
}
|
||||
|
||||
static int64_t uwsgi_metric_collector_accumulator(struct uwsgi_metric *um) {
|
||||
int64_t total = *um->value;
|
||||
struct uwsgi_metric_child *umc = um->children;
|
||||
while(umc) {
|
||||
struct uwsgi_metric *c = umc->um;
|
||||
total += *c->value;
|
||||
umc = umc->next;
|
||||
}
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
static int64_t uwsgi_metric_collector_multiplier(struct uwsgi_metric *um) {
|
||||
int64_t total = 0;
|
||||
struct uwsgi_metric_child *umc = um->children;
|
||||
while(umc) {
|
||||
struct uwsgi_metric *c = umc->um;
|
||||
total += *c->value;
|
||||
umc = umc->next;
|
||||
}
|
||||
|
||||
return total * um->arg1n;
|
||||
}
|
||||
|
||||
static int64_t uwsgi_metric_collector_adder(struct uwsgi_metric *um) {
|
||||
int64_t total = 0;
|
||||
struct uwsgi_metric_child *umc = um->children;
|
||||
while(umc) {
|
||||
struct uwsgi_metric *c = umc->um;
|
||||
total += *c->value;
|
||||
umc = umc->next;
|
||||
}
|
||||
|
||||
return total + um->arg1n;
|
||||
}
|
||||
|
||||
static int64_t uwsgi_metric_collector_avg(struct uwsgi_metric *um) {
|
||||
int64_t total = 0;
|
||||
int64_t count = 0;
|
||||
@@ -1001,6 +1040,9 @@ void uwsgi_metrics_collectors_setup() {
|
||||
uwsgi_register_metric_collector("ptr", uwsgi_metric_collector_ptr);
|
||||
uwsgi_register_metric_collector("file", uwsgi_metric_collector_file);
|
||||
uwsgi_register_metric_collector("sum", uwsgi_metric_collector_sum);
|
||||
uwsgi_register_metric_collector("accumulator", uwsgi_metric_collector_accumulator);
|
||||
uwsgi_register_metric_collector("adder", uwsgi_metric_collector_adder);
|
||||
uwsgi_register_metric_collector("multiplier", uwsgi_metric_collector_multiplier);
|
||||
uwsgi_register_metric_collector("avg", uwsgi_metric_collector_avg);
|
||||
uwsgi_register_metric_collector("func", uwsgi_metric_collector_func);
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ void uwsgi_mule(int id) {
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_hooks_run(uwsgi.hook_as_mule, "as-mule", 1);
|
||||
uwsgi_mule_run();
|
||||
|
||||
}
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
#include "uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
#define UWSGI_BUILD_DIR ".uwsgi_plugins_builder"
|
||||
|
||||
/*
|
||||
|
||||
steps:
|
||||
|
||||
mkdir(.uwsgi_plugin_builder)
|
||||
generate .uwsgi_plugin_builder/uwsgi.h
|
||||
generate .uwsgi_plugin_builder/uwsgiconfig.py
|
||||
setenv(UWSGI_PLUGINS_BUILDER_CFLAGS=uwsgi_cflags)
|
||||
exec PYTHON .uwsgi_plugin_builder/uwsgiconfig.py --extra-plugin <directory> [name]
|
||||
|
||||
*/
|
||||
|
||||
void uwsgi_build_plugin(char *directory) {
|
||||
|
||||
if (!uwsgi_file_exists(UWSGI_BUILD_DIR)) {
|
||||
if (mkdir(UWSGI_BUILD_DIR, S_IRWXU) < 0) {
|
||||
uwsgi_error("uwsgi_build_plugin()/mkdir() " UWSGI_BUILD_DIR "/");
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
char *dot_h = uwsgi_get_dot_h();
|
||||
if (!dot_h) {
|
||||
uwsgi_log("unable to generate uwsgi.h");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (strlen(dot_h) == 0) {
|
||||
free(dot_h);
|
||||
uwsgi_log("invalid uwsgi.h");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
int dot_h_fd = open(UWSGI_BUILD_DIR "/uwsgi.h", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
|
||||
if (dot_h_fd < 0) {
|
||||
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgi.h");
|
||||
free(dot_h);
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
ssize_t dot_h_len = (ssize_t) strlen(dot_h);
|
||||
if (write(dot_h_fd, dot_h, dot_h_len) != dot_h_len) {
|
||||
uwsgi_error("uwsgi_build_plugin()/write()");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
char *config_py = uwsgi_get_config_py();
|
||||
if (!config_py) {
|
||||
uwsgi_log("unable to generate uwsgiconfig.py");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (strlen(config_py) == 0) {
|
||||
uwsgi_log("invalid uwsgiconfig.py");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
int config_py_fd = open(UWSGI_BUILD_DIR "/uwsgiconfig.py", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
|
||||
if (config_py_fd < 0) {
|
||||
uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgiconfig.py");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
ssize_t config_py_len = (ssize_t) strlen(config_py);
|
||||
if (write(config_py_fd, config_py, config_py_len) != config_py_len) {
|
||||
uwsgi_error("uwsgi_build_plugin()/write()");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
char *cflags = uwsgi_get_cflags();
|
||||
if (!cflags) {
|
||||
uwsgi_log("unable to find cflags\n");
|
||||
_exit(1);
|
||||
}
|
||||
if (strlen(cflags) == 0) {
|
||||
uwsgi_log("invalid cflags\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
if (setenv("UWSGI_PLUGINS_BUILDER_CFLAGS", cflags, 1)) {
|
||||
uwsgi_error("uwsgi_build_plugin()/setenv()");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
// now run the python script
|
||||
char *argv[6];
|
||||
|
||||
argv[0] = getenv("PYTHON");
|
||||
if (!argv[0]) argv[0] = "python";
|
||||
|
||||
argv[1] = UWSGI_BUILD_DIR "/uwsgiconfig.py";
|
||||
argv[2] = "--extra-plugin";
|
||||
char *space = strchr(directory, ' ');
|
||||
if (space) {
|
||||
*space = 0;
|
||||
argv[3] = directory;
|
||||
argv[4] = space+1;
|
||||
argv[5] = NULL;
|
||||
}
|
||||
else {
|
||||
argv[3] = directory;
|
||||
argv[4] = NULL;
|
||||
}
|
||||
|
||||
execvp(argv[0], argv);
|
||||
// never here...
|
||||
_exit(1);
|
||||
}
|
||||
+66
-11
@@ -24,6 +24,39 @@ int uwsgi_simple_wait_read_hook(int fd, int timeout) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_simple_wait_read2_hook(int fd0, int fd1, int timeout, int *fd) {
|
||||
struct pollfd upoll[2];
|
||||
timeout = timeout * 1000;
|
||||
|
||||
upoll[0].fd = fd0;
|
||||
upoll[0].events = POLLIN;
|
||||
upoll[0].revents = 0;
|
||||
|
||||
upoll[1].fd = fd1;
|
||||
upoll[1].events = POLLIN;
|
||||
upoll[1].revents = 0;
|
||||
|
||||
int ret = poll(upoll, 2, timeout);
|
||||
|
||||
if (ret > 0) {
|
||||
if (upoll[0].revents & POLLIN) {
|
||||
*fd = fd0;
|
||||
return 1;
|
||||
}
|
||||
if (upoll[1].revents & POLLIN) {
|
||||
*fd = fd1;
|
||||
return 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_error("uwsgi_simple_wait_read_hook2()/poll()");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
seek()/rewind() language-independent implementations.
|
||||
*/
|
||||
@@ -32,14 +65,16 @@ void uwsgi_request_body_seek(struct wsgi_request *wsgi_req, off_t pos) {
|
||||
if (wsgi_req->post_file) {
|
||||
if (pos < 0) {
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_CUR)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
}
|
||||
|
||||
if (fseek(wsgi_req->post_file, pos, SEEK_SET)) {
|
||||
uwsgi_error("uwsgi_request_body_seek()/fseek()");
|
||||
uwsgi_req_error("uwsgi_request_body_seek()/fseek()");
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
wsgi_req->post_pos = ftell(wsgi_req->post_file);
|
||||
return;
|
||||
@@ -95,7 +130,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->post_readline_size - wsgi_req->post_readline_watermark < remains) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_readline_buf, wsgi_req->post_readline_size + remains);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("consume_body_for_readline()/realloc()");
|
||||
uwsgi_req_error("consume_body_for_readline()/realloc()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_readline_buf = tmp_buf;
|
||||
@@ -114,7 +149,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->post_file) {
|
||||
size_t ret = fread(wsgi_req->post_readline_buf + wsgi_req->post_readline_watermark, remains, 1, wsgi_req->post_file);
|
||||
if (ret == 0) {
|
||||
uwsgi_error("consume_body_for_readline()/fread()");
|
||||
uwsgi_req_error("consume_body_for_readline()/fread()");
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->post_pos += remains;
|
||||
@@ -140,6 +175,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
if (len == 0) {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (len < 0) {
|
||||
@@ -147,6 +183,7 @@ static int consume_body_for_readline(struct wsgi_request *wsgi_req) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
wait:
|
||||
@@ -159,6 +196,7 @@ wait:
|
||||
return 0;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
// 0 means timeout
|
||||
@@ -167,6 +205,7 @@ wait:
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -204,7 +243,8 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
|
||||
size_t amount = UMIN(uwsgi.buffer_size, wsgi_req->post_cl);
|
||||
wsgi_req->post_readline_buf = malloc(amount);
|
||||
if (!wsgi_req->post_readline_buf) {
|
||||
uwsgi_error("uwsgi_request_body_readline()/malloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_readline()/malloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -217,6 +257,7 @@ char *uwsgi_request_body_readline(struct wsgi_request *wsgi_req, ssize_t hint, s
|
||||
if (wsgi_req->post_pos >= wsgi_req->post_cl) break;
|
||||
|
||||
if (consume_body_for_readline(wsgi_req)) {
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -272,8 +313,9 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (avail > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, avail);
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
|
||||
*rlen = -1;
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
wsgi_req->post_read_buf = tmp_buf;
|
||||
@@ -320,7 +362,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
wsgi_req->post_read_buf = malloc(remains);
|
||||
if (!wsgi_req->post_read_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/malloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/malloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -331,7 +374,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if ((remains+*rlen) > wsgi_req->post_read_buf_size) {
|
||||
char *tmp_buf = realloc(wsgi_req->post_read_buf, (remains+*rlen));
|
||||
if (!tmp_buf) {
|
||||
uwsgi_error("uwsgi_request_body_read()/realloc()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/realloc()");
|
||||
wsgi_req->read_errors++;
|
||||
*rlen = -1;
|
||||
return NULL;
|
||||
}
|
||||
@@ -348,7 +392,8 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
if (wsgi_req->post_file) {
|
||||
if (fread(wsgi_req->post_read_buf + *rlen, remains, 1, wsgi_req->post_file) != 1) {
|
||||
*rlen = -1;
|
||||
uwsgi_error("uwsgi_request_body_read()/fread()");
|
||||
uwsgi_req_error("uwsgi_request_body_read()/fread()");
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
*rlen += remains;
|
||||
@@ -378,6 +423,7 @@ char *uwsgi_request_body_read(struct wsgi_request *wsgi_req, ssize_t hint, ssize
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
wait:
|
||||
@@ -398,6 +444,7 @@ wait:
|
||||
}
|
||||
else {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
@@ -409,6 +456,7 @@ wait:
|
||||
}
|
||||
*rlen = -1;
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -447,6 +495,7 @@ int uwsgi_postbuffer_do_in_mem(struct wsgi_request *wsgi_req) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -462,6 +511,7 @@ wait:
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
uwsgi_read_timeout(remains);
|
||||
@@ -482,7 +532,8 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
|
||||
wsgi_req->post_file = uwsgi_tmpfile();
|
||||
if (!wsgi_req->post_file) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
|
||||
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/uwsgi_tmpfile()");
|
||||
wsgi_req->read_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -518,6 +569,7 @@ int uwsgi_postbuffer_do_in_disk(struct wsgi_request *wsgi_req) {
|
||||
goto wait;
|
||||
}
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -531,11 +583,13 @@ wait:
|
||||
}
|
||||
else {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
}
|
||||
goto end;
|
||||
}
|
||||
if (ret < 0) {
|
||||
uwsgi_read_error(remains);
|
||||
wsgi_req->read_errors++;
|
||||
goto end;
|
||||
}
|
||||
uwsgi_read_timeout(remains);
|
||||
@@ -543,7 +597,8 @@ wait:
|
||||
|
||||
write:
|
||||
if (fwrite(wsgi_req->post_buffering_buf, rlen, 1, wsgi_req->post_file) != 1) {
|
||||
uwsgi_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
|
||||
uwsgi_req_error("uwsgi_postbuffer_do_in_disk()/fwrite()");
|
||||
wsgi_req->read_errors++;
|
||||
goto end;
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -962,7 +962,7 @@ static int uwsgi_router_chdir_func(struct wsgi_request *wsgi_req, struct uwsgi_r
|
||||
struct uwsgi_buffer *ub = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, ur->data, ur->data_len);
|
||||
if (!ub) return UWSGI_ROUTE_BREAK;
|
||||
if (chdir(ub->buf)) {
|
||||
uwsgi_error("uwsgi_router_chdir_func()/chdir()");
|
||||
uwsgi_req_error("uwsgi_router_chdir_func()/chdir()");
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return UWSGI_ROUTE_BREAK;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
/*
|
||||
|
||||
This is an high-performance memory area shared by all workers/cores/threads
|
||||
|
||||
Contrary to the caching subsystem it is 1-copy (caching for non-c apps is 2-copy)
|
||||
|
||||
Languages not allowing that kind of access should emulate it calling uwsgi_malloc and then copying it back to
|
||||
the language object.
|
||||
|
||||
The memory areas could be monitored for changes (read: cores can be suspended while waiting for values)
|
||||
|
||||
You can configure multiple areas specifying multiple --sharedarea options
|
||||
|
||||
This is a very low-level api, try to use it to build higher-level primitives or rely on the caching subsystem
|
||||
|
||||
*/
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int id, uint64_t pos) {
|
||||
if (id > uwsgi.sharedareas_cnt-1) return NULL;
|
||||
struct uwsgi_sharedarea *sa = uwsgi.sharedareas[id];
|
||||
if (pos > sa->max_pos) return NULL;
|
||||
return sa;
|
||||
}
|
||||
|
||||
int64_t uwsgi_sharedarea_read(int id, uint64_t pos, char *blob, uint64_t len) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + len > sa->max_pos + 1) return -1;
|
||||
if (len == 0) len = (sa->max_pos + 1) - pos;
|
||||
if (sa->honour_used && sa->used-pos < len) len = sa->used-pos ;
|
||||
uwsgi_rlock(sa->lock);
|
||||
memcpy(blob, sa->area + pos, len);
|
||||
sa->hits++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return len;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write(int id, uint64_t pos, char *blob, uint64_t len) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + len > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
memcpy(sa->area + pos, blob, len);
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read64(int id, uint64_t pos, int64_t *value) {
|
||||
return uwsgi_sharedarea_read(id, pos, (char *) value, 8);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write64(int id, uint64_t pos, int64_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 8);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read8(int id, uint64_t pos, int8_t *value) {
|
||||
return uwsgi_sharedarea_read(id, pos, (char *) value, 1);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write8(int id, uint64_t pos, int8_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 1);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_read16(int id, uint64_t pos, int16_t *value) {
|
||||
return uwsgi_sharedarea_read(id, pos, (char *) value, 2);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write16(int id, uint64_t pos, int16_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 2);
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_sharedarea_read32(int id, uint64_t pos, int32_t *value) {
|
||||
return uwsgi_sharedarea_read(id, pos, (char *) value, 4);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_write32(int id, uint64_t pos, int32_t *value) {
|
||||
return uwsgi_sharedarea_write(id, pos, (char *) value, 4);
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc8(int id, uint64_t pos, int8_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 1 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int8_t *n_ptr = (int8_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc16(int id, uint64_t pos, int16_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 2 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int16_t *n_ptr = (int16_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc32(int id, uint64_t pos, int32_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int32_t *n_ptr = (int32_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_inc64(int id, uint64_t pos, int64_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int64_t *n_ptr = (int64_t *) (sa->area + pos);
|
||||
*n_ptr+=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_sharedarea_dec8(int id, uint64_t pos, int8_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 1 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int8_t *n_ptr = (int8_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec16(int id, uint64_t pos, int16_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 2 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int16_t *n_ptr = (int16_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec32(int id, uint64_t pos, int32_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int32_t *n_ptr = (int32_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_dec64(int id, uint64_t pos, int64_t amount) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (pos + 4 > sa->max_pos + 1) return -1;
|
||||
uwsgi_wlock(sa->lock);
|
||||
int64_t *n_ptr = (int64_t *) (sa->area + pos);
|
||||
*n_ptr-=amount;
|
||||
sa->updates++;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
returns:
|
||||
0 -> on updates
|
||||
-1 -> on error
|
||||
-2 -> on timeout
|
||||
*/
|
||||
int uwsgi_sharedarea_wait(int id, int freq, int timeout) {
|
||||
int waiting = 0;
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, 0);
|
||||
if (!sa) return -1;
|
||||
if (!freq) freq = 100;
|
||||
uwsgi_rlock(sa->lock);
|
||||
uint64_t updates = sa->updates;
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
while(timeout == 0 || (timeout > 0 && (waiting/1000) >= timeout)) {
|
||||
uwsgi.wait_milliseconds_hook(freq);
|
||||
waiting += freq;
|
||||
// lock sa
|
||||
uwsgi_rlock(sa->lock);
|
||||
if (sa->updates != updates) {
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
return 0;
|
||||
}
|
||||
// unlock sa
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int uwsgi_sharedarea_new_id() {
|
||||
int id = uwsgi.sharedareas_cnt;
|
||||
uwsgi.sharedareas_cnt++;
|
||||
if (!uwsgi.sharedareas) {
|
||||
uwsgi.sharedareas = uwsgi_malloc(sizeof(struct uwsgi_sharedarea *));
|
||||
}
|
||||
else {
|
||||
struct uwsgi_sharedarea **usa = realloc(uwsgi.sharedareas, ((sizeof(struct uwsgi_sharedarea *)) * uwsgi.sharedareas_cnt));
|
||||
if (!usa) {
|
||||
uwsgi_error("uwsgi_sharedarea_init()/realloc()");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.sharedareas = usa;
|
||||
}
|
||||
return id;
|
||||
}
|
||||
|
||||
static struct uwsgi_sharedarea *announce_sa(struct uwsgi_sharedarea *sa) {
|
||||
uwsgi_log("sharedarea %d created at %p (%d pages, area at %p)\n", sa->id, sa, sa->pages, sa->area);
|
||||
return sa;
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int pages) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(uwsgi.page_size * (pages + 1));
|
||||
uwsgi.sharedareas[id]->area = ((char *) uwsgi.sharedareas[id]) + uwsgi.page_size;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = pages;
|
||||
uwsgi.sharedareas[id]->max_pos = (uwsgi.page_size * pages) -1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *area, uint64_t len) {
|
||||
int id = uwsgi_sharedarea_new_id();
|
||||
uwsgi.sharedareas[id] = uwsgi_calloc_shared(sizeof(struct uwsgi_sharedarea));
|
||||
uwsgi.sharedareas[id]->area = area;
|
||||
uwsgi.sharedareas[id]->id = id;
|
||||
uwsgi.sharedareas[id]->fd = -1;
|
||||
uwsgi.sharedareas[id]->pages = len / uwsgi.page_size;
|
||||
if (len % uwsgi.page_size != 0) uwsgi.sharedareas[id]->pages++;
|
||||
uwsgi.sharedareas[id]->max_pos = len-1;
|
||||
char *id_str = uwsgi_num2str(id);
|
||||
uwsgi.sharedareas[id]->lock = uwsgi_rwlock_init(uwsgi_concat2("sharedarea", id_str));
|
||||
free(id_str);
|
||||
return announce_sa(uwsgi.sharedareas[id]);
|
||||
}
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_keyval(char *arg) {
|
||||
char *s_pages = NULL;
|
||||
char *s_file = NULL;
|
||||
char *s_fd = NULL;
|
||||
char *s_ptr = NULL;
|
||||
char *s_size = NULL;
|
||||
if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
|
||||
"pages", &s_pages,
|
||||
"file", &s_file,
|
||||
"fd", &s_fd,
|
||||
"ptr", &s_ptr,
|
||||
"size", &s_size,
|
||||
NULL)) {
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_sharedareas_init() {
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.sharedareas_list) {
|
||||
char *is_keyval = strchr(usl->value, '=');
|
||||
if (!is_keyval) {
|
||||
uwsgi_sharedarea_init(atoi(usl->value));
|
||||
}
|
||||
else {
|
||||
uwsgi_sharedarea_init_keyval(usl->value);
|
||||
}
|
||||
}
|
||||
}
|
||||
+4
-3
@@ -1931,17 +1931,18 @@ found:
|
||||
void uwsgi_protocols_register() {
|
||||
uwsgi_register_protocol("uwsgi", uwsgi_proto_uwsgi_setup);
|
||||
uwsgi_register_protocol("puwsgi", uwsgi_proto_puwsgi_setup);
|
||||
|
||||
uwsgi_register_protocol("http", uwsgi_proto_http_setup);
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
uwsgi_register_protocol("suwsgi", uwsgi_proto_suwsgi_setup);
|
||||
uwsgi_register_protocol("https", uwsgi_proto_https_setup);
|
||||
#endif
|
||||
uwsgi_register_protocol("fastcgi", uwsgi_proto_fastcgi_setup);
|
||||
uwsgi_register_protocol("fastcgi-nph", uwsgi_proto_fastcgi_nph_setup);
|
||||
|
||||
uwsgi_register_protocol("scgi", uwsgi_proto_scgi_setup);
|
||||
uwsgi_register_protocol("scgi-nph", uwsgi_proto_scgi_nph_setup);
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
uwsgi_register_protocol("zmq", uwsgi_proto_zmq_setup);
|
||||
#endif
|
||||
|
||||
uwsgi_register_protocol("raw", uwsgi_proto_raw_setup);
|
||||
}
|
||||
|
||||
@@ -812,6 +812,8 @@ end:
|
||||
}
|
||||
|
||||
void uwsgi_subscribe_all(uint8_t cmd, int verbose) {
|
||||
|
||||
if (!uwsgi.subscriptions_blocked) return;
|
||||
// -- subscribe
|
||||
struct uwsgi_string_list *subscriptions = uwsgi.subscriptions;
|
||||
while (subscriptions) {
|
||||
|
||||
+15
-4
@@ -1038,6 +1038,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
uwsgi.workers[uwsgi.mywid].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].requests++;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].write_errors += wsgi_req->write_errors;
|
||||
uwsgi.workers[uwsgi.mywid].cores[wsgi_req->async_id].read_errors += wsgi_req->read_errors;
|
||||
// this is used for MAX_REQUESTS
|
||||
uwsgi.workers[uwsgi.mywid].delta_requests++;
|
||||
}
|
||||
@@ -1073,6 +1074,13 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
if (!wsgi_req->is_raw && uwsgi.p[wsgi_req->uh->modifier1]->after_request)
|
||||
uwsgi.p[wsgi_req->uh->modifier1]->after_request(wsgi_req);
|
||||
|
||||
// after_request custom hooks
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
uwsgi_foreach(usl, uwsgi.after_request_hooks) {
|
||||
void (*func)(struct wsgi_request *) = (void (*)(struct wsgi_request *)) usl->custom_ptr;
|
||||
func(wsgi_req);
|
||||
}
|
||||
|
||||
if (uwsgi.threads > 1) {
|
||||
// now the thread can die...
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &tmp_id);
|
||||
@@ -1137,6 +1145,9 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->websocket_buf) {
|
||||
uwsgi_buffer_destroy(wsgi_req->websocket_buf);
|
||||
}
|
||||
if (wsgi_req->websocket_send_buf) {
|
||||
uwsgi_buffer_destroy(wsgi_req->websocket_send_buf);
|
||||
}
|
||||
|
||||
|
||||
// reset request
|
||||
@@ -1162,7 +1173,7 @@ void uwsgi_close_request(struct wsgi_request *wsgi_req) {
|
||||
}
|
||||
|
||||
|
||||
// ready to accept request, if i am a vassal signal Emperor about my loyalty
|
||||
// after the first request, if i am a vassal, signal Emperor about my loyalty
|
||||
if (uwsgi.has_emperor && !uwsgi.loyal) {
|
||||
uwsgi_log("announcing my loyalty to the Emperor...\n");
|
||||
char byte = 17;
|
||||
@@ -3922,9 +3933,9 @@ char *uwsgi_strip(char *src) {
|
||||
|
||||
void uwsgi_uuid(char *buf) {
|
||||
#ifdef UWSGI_UUID
|
||||
uuid_t uuid_zmq;
|
||||
uuid_generate(uuid_zmq);
|
||||
uuid_unparse(uuid_zmq, buf);
|
||||
uuid_t uuid_value;
|
||||
uuid_generate(uuid_value);
|
||||
uuid_unparse(uuid_value, buf);
|
||||
#else
|
||||
int i,r[11];
|
||||
if (!uwsgi_file_exists("/dev/urandom")) goto fallback;
|
||||
|
||||
+120
-49
@@ -241,7 +241,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"worker-reload-mercy", required_argument, 0, "set the maximum time (in seconds) a worker can take to reload/shutdown (default is 60)", uwsgi_opt_set_int, &uwsgi.worker_reload_mercy, 0},
|
||||
{"exit-on-reload", no_argument, 0, "force exit even if a reload is requested", uwsgi_opt_true, &uwsgi.exit_on_reload, 0},
|
||||
{"die-on-term", no_argument, 0, "exit instead of brutal reload on SIGTERM", uwsgi_opt_true, &uwsgi.die_on_term, 0},
|
||||
{"force-gateway", no_argument, 0, "force teh spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
|
||||
{"force-gateway", no_argument, 0, "force the spawn of the first registered gateway without a master", uwsgi_opt_true, &uwsgi.force_gateway, 0},
|
||||
{"help", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"usage", no_argument, 'h', "show this help", uwsgi_help, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
|
||||
@@ -259,7 +259,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"lock-engine", required_argument, 0, "set the lock engine", uwsgi_opt_set_str, &uwsgi.lock_engine, 0},
|
||||
{"ftok", required_argument, 0, "set the ipcsem key via ftok() for avoiding duplicates", uwsgi_opt_set_str, &uwsgi.ftok, 0},
|
||||
{"persistent-ipcsem", no_argument, 0, "do not remove ipcsem's on shutdown", uwsgi_opt_true, &uwsgi.persistent_ipcsem, 0},
|
||||
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages", uwsgi_opt_set_int, &uwsgi.sharedareasize, 0},
|
||||
{"sharedarea", required_argument, 'A', "create a raw shared memory area of specified pages (note: it supports keyval too)", uwsgi_opt_add_string_list, &uwsgi.sharedareas_list, 0},
|
||||
|
||||
{"safe-fd", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
{"fd-safe", required_argument, 0, "do not close the specified file descriptor", uwsgi_opt_safe_fd, NULL, 0},
|
||||
@@ -373,9 +373,18 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"hook-as-user-atexit", required_argument, 0, "run the specified hook before app exit and reload", uwsgi_opt_add_string_list, &uwsgi.hook_as_user_atexit, 0},
|
||||
{"hook-pre-app", required_argument, 0, "run the specified hook before app loading", uwsgi_opt_add_string_list, &uwsgi.hook_pre_app, 0},
|
||||
{"hook-post-app", required_argument, 0, "run the specified hook after app loading", uwsgi_opt_add_string_list, &uwsgi.hook_post_app, 0},
|
||||
{"hook-accepting", required_argument, 0, "run the specified hook after each worker enter the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting, 0},
|
||||
{"hook-accepting1", required_argument, 0, "run the specified hook after the first worker enters the accepting phase", uwsgi_opt_add_string_list, &uwsgi.hook_accepting1, 0},
|
||||
{"hook-accepting-once", required_argument, 0, "run the specified hook after each worker enter the accepting phase (once per-instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting_once, 0},
|
||||
{"hook-accepting1-once", required_argument, 0, "run the specified hook after the first worker enters the accepting phase (once per instance)", uwsgi_opt_add_string_list, &uwsgi.hook_accepting1_once, 0},
|
||||
|
||||
{"hook-as-vassal", required_argument, 0, "run the specified command before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.hook_as_vassal, 0},
|
||||
{"hook-as-emperor", required_argument, 0, "run the specified command in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.hook_as_emperor, 0},
|
||||
{"hook-as-vassal", required_argument, 0, "run the specified hook before exec()ing the vassal", uwsgi_opt_add_string_list, &uwsgi.hook_as_vassal, 0},
|
||||
{"hook-as-emperor", required_argument, 0, "run the specified hook in the emperor after the vassal has been started", uwsgi_opt_add_string_list, &uwsgi.hook_as_emperor, 0},
|
||||
|
||||
{"hook-as-mule", required_argument, 0, "run the specified hook in each mule", uwsgi_opt_add_string_list, &uwsgi.hook_as_mule, 0},
|
||||
|
||||
{"after-request-hook", required_argument, 0, "run the specified function/symbol after each request", uwsgi_opt_add_string_list, &uwsgi.after_request_hooks, 0},
|
||||
{"after-request-call", required_argument, 0, "run the specified function/symbol after each request", uwsgi_opt_add_string_list, &uwsgi.after_request_hooks, 0},
|
||||
|
||||
{"exec-asap", required_argument, 0, "run the specified command as soon as possible", uwsgi_opt_add_string_list, &uwsgi.exec_asap, 0},
|
||||
{"exec-pre-jail", required_argument, 0, "run the specified command before jailing", uwsgi_opt_add_string_list, &uwsgi.exec_pre_jail, 0},
|
||||
@@ -449,12 +458,6 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#ifdef UWSGI_JSON
|
||||
{"json", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"js", required_argument, 'j', "load config from json file", uwsgi_opt_load_json, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
#endif
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
{"zeromq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zeromq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
{"zmq-socket", required_argument, 0, "create a zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "zmq", 0},
|
||||
#endif
|
||||
{"weight", required_argument, 0, "weight of the instance (used by clustering/lb/subscriptions)", uwsgi_opt_set_64bit, &uwsgi.weight, 0},
|
||||
{"auto-weight", required_argument, 0, "set weight of the instance (used by clustering/lb/subscriptions) automatically", uwsgi_opt_true, &uwsgi.auto_weight, 0},
|
||||
@@ -649,9 +652,6 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"alarm-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
{"alarms-list", no_argument, 0, "list enabled alarms", uwsgi_opt_true, &uwsgi.alarms_list, 0},
|
||||
{"alarm-msg-size", required_argument, 0, "set the max size of an alarm message (default 8192)", uwsgi_opt_set_64bit, &uwsgi.alarm_msg_size, 0},
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
{"log-zeromq", required_argument, 0, "send logs to a zeromq server", uwsgi_opt_set_logger, "zeromq", UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
#endif
|
||||
{"log-master", no_argument, 0, "delegate logging to master process", uwsgi_opt_true, &uwsgi.log_master, UWSGI_OPT_MASTER},
|
||||
{"log-master-bufsize", required_argument, 0, "set the buffer size for the master logger. bigger log messages will be truncated", uwsgi_opt_set_64bit, &uwsgi.log_master_bufsize, 0},
|
||||
{"log-master-stream", no_argument, 0, "create the master logpipe as SOCK_STREAM", uwsgi_opt_true, &uwsgi.log_master_stream, 0},
|
||||
@@ -671,6 +671,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"log-5xx", no_argument, 0, "log requests with a 5xx response", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_5xx, 0},
|
||||
{"log-big", required_argument, 0, "log requestes bigger than the specified size", uwsgi_opt_set_dyn, (void *) UWSGI_OPTION_LOG_BIG, 0},
|
||||
{"log-sendfile", required_argument, 0, "log sendfile requests", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_SENDFILE, 0},
|
||||
{"log-ioerror", required_argument, 0, "log requests with io errors", uwsgi_opt_dyn_true, (void *) UWSGI_OPTION_LOG_IOERROR, 0},
|
||||
{"log-micros", no_argument, 0, "report response time in microseconds instead of milliseconds", uwsgi_opt_true, &uwsgi.log_micros, 0},
|
||||
{"log-x-forwarded-for", no_argument, 0, "use the ip from X-Forwarded-For header instead of REMOTE_ADDR", uwsgi_opt_true, &uwsgi.log_x_forwarded_for, 0},
|
||||
{"master-as-root", no_argument, 0, "leave master process running as root", uwsgi_opt_true, &uwsgi.master_as_root, 0},
|
||||
@@ -770,6 +771,11 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"routers-list", no_argument, 0, "list enabled routers", uwsgi_opt_true, &uwsgi.router_list, 0},
|
||||
#endif
|
||||
|
||||
|
||||
{"error-page-403", required_argument, 0, "add an error page (html) for managed 403 response", uwsgi_opt_add_string_list, &uwsgi.error_page_403, 0},
|
||||
{"error-page-404", required_argument, 0, "add an error page (html) for managed 404 response", uwsgi_opt_add_string_list, &uwsgi.error_page_404, 0},
|
||||
{"error-page-500", required_argument, 0, "add an error page (html) for managed 500 response", uwsgi_opt_add_string_list, &uwsgi.error_page_500, 0},
|
||||
|
||||
{"websockets-ping-freq", required_argument, 0, "set the frequency (in seconds) of websockets automatic ping packets", uwsgi_opt_set_int, &uwsgi.websockets_ping_freq, 0},
|
||||
{"websocket-ping-freq", required_argument, 0, "set the frequency (in seconds) of websockets automatic ping packets", uwsgi_opt_set_int, &uwsgi.websockets_ping_freq, 0},
|
||||
|
||||
@@ -886,7 +892,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"worker-exec", required_argument, 0, "run the specified command as worker", uwsgi_opt_set_str, &uwsgi.worker_exec, 0},
|
||||
{"worker-exec2", required_argument, 0, "run the specified command as worker (after post_fork hook)", uwsgi_opt_set_str, &uwsgi.worker_exec2, 0},
|
||||
{"attach-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"attach-control-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background), when teh daemon dies, the master dies too", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"attach-control-daemon", required_argument, 0, "attach a command/daemon to the master process (the command has to not go in background), when the daemon dies, the master dies too", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
{"smart-attach-daemon2", required_argument, 0, "attach a command/daemon to the master process managed by a pidfile (the command has to NOT daemonize)", uwsgi_opt_add_daemon, NULL, UWSGI_OPT_MASTER},
|
||||
#ifdef UWSGI_SSL
|
||||
@@ -916,6 +922,8 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"exit", optional_argument, 0, "force exit() of the instance", uwsgi_opt_exit, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"cflags", no_argument, 0, "report uWSGI CFLAGS (useful for building external plugins)", uwsgi_opt_cflags, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"dot-h", no_argument, 0, "dump the uwsgi.h used for building the core (useful for building external plugins)", uwsgi_opt_dot_h, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"config-py", no_argument, 0, "dump the uwsgiconfig.py used for building the core (useful for building external plugins)", uwsgi_opt_config_py, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"build-plugin", required_argument, 0, "build a uWSGI plugin for the current binary", uwsgi_opt_build_plugin, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{"version", no_argument, 0, "print uWSGI version", uwsgi_opt_print, UWSGI_VERSION, 0},
|
||||
{0, 0, 0, 0, 0, 0, 0}
|
||||
};
|
||||
@@ -1847,14 +1855,19 @@ void uwsgi_init_random() {
|
||||
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
int uwsgi_init(int argc, char *argv[], char *envp[]) {
|
||||
#else
|
||||
int main(int argc, char *argv[], char *envp[]) {
|
||||
#endif
|
||||
uwsgi_setup(argc, argv, envp);
|
||||
return uwsgi_run();
|
||||
}
|
||||
|
||||
void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
#ifdef __APPLE__
|
||||
char ***envPtr = _NSGetEnviron();
|
||||
environ = *envPtr;
|
||||
#endif
|
||||
|
||||
#else
|
||||
int main(int argc, char *argv[], char *envp[]) {
|
||||
#endif
|
||||
|
||||
int i;
|
||||
@@ -1990,11 +2003,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
}
|
||||
uwsgi.hostname_len = strlen(uwsgi.hostname);
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
uwsgi_register_logger("zeromq", uwsgi_zeromq_logger);
|
||||
uwsgi_register_logger("zmq", uwsgi_zeromq_logger);
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
uwsgi_register_embedded_routers();
|
||||
#endif
|
||||
@@ -2318,7 +2326,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO pluginize basic Linux namespace support
|
||||
#if defined(__linux__) && !defined(__ia64__)
|
||||
if (uwsgi.ns) {
|
||||
@@ -2331,10 +2338,6 @@ int main(int argc, char *argv[], char *envp[]) {
|
||||
#if defined(__linux__) && !defined(__ia64__)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// never here
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -2526,9 +2529,6 @@ int uwsgi_start(void *v_argv) {
|
||||
}
|
||||
}
|
||||
uwsgi_log_initial("- async cores set to %d - fd table size: %d\n", uwsgi.async, (int) uwsgi.max_fd);
|
||||
// optimization, this array maps file descriptor to requests
|
||||
uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
|
||||
}
|
||||
|
||||
#ifdef UWSGI_DEBUG
|
||||
@@ -2551,12 +2551,8 @@ int uwsgi_start(void *v_argv) {
|
||||
// allocate rpc structures
|
||||
uwsgi_rpc_init();
|
||||
|
||||
// setup sharedarea
|
||||
if (uwsgi.sharedareasize > 0) {
|
||||
uwsgi.sharedarea = uwsgi_calloc_shared(uwsgi.page_size * uwsgi.sharedareasize);
|
||||
uwsgi_log("shared area mapped at %p, you can access it with uwsgi.sharedarea* functions.\n", uwsgi.sharedarea);
|
||||
uwsgi.sa_lock = uwsgi_rwlock_init("sharedarea");
|
||||
}
|
||||
// initialize sharedareas
|
||||
uwsgi_sharedareas_init();
|
||||
|
||||
uwsgi.snmp_lock = uwsgi_lock_init("snmp");
|
||||
|
||||
@@ -2615,6 +2611,7 @@ int uwsgi_start(void *v_argv) {
|
||||
uwsgi_setup_systemd();
|
||||
uwsgi_setup_upstart();
|
||||
uwsgi_setup_zerg();
|
||||
uwsgi_setup_emperor();
|
||||
}
|
||||
|
||||
|
||||
@@ -2907,6 +2904,15 @@ next:
|
||||
}
|
||||
}
|
||||
|
||||
// initialize after_request hooks
|
||||
uwsgi_foreach(usl, uwsgi.after_request_hooks) {
|
||||
usl->custom_ptr = dlsym(RTLD_DEFAULT, usl->value);
|
||||
if (!usl->custom_ptr) {
|
||||
uwsgi_log("unable to find symbol/function \"%s\"\n", usl->value);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("added \"%s(struct wsgi_request *)\" to the after-request chain\n", usl->value);
|
||||
}
|
||||
|
||||
if (uwsgi.daemonize2) {
|
||||
masterpid = uwsgi_daemonize2();
|
||||
@@ -3050,9 +3056,14 @@ next2:
|
||||
|
||||
|
||||
// END OF INITIALIZATION
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_run() {
|
||||
|
||||
// !!! from now on, we could be in the master or in a worker !!!
|
||||
|
||||
int i;
|
||||
|
||||
if (getpid() == masterpid && uwsgi.master_process == 1) {
|
||||
#ifdef UWSGI_AS_SHARED_LIBRARY
|
||||
@@ -3166,18 +3177,17 @@ void uwsgi_worker_run() {
|
||||
// some apps could be mounted only on specific workers
|
||||
uwsgi_init_worker_mount_apps();
|
||||
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
// setup zeromq context (if required) one per-worker
|
||||
if (uwsgi.zeromq) {
|
||||
uwsgi_zeromq_init_sockets();
|
||||
}
|
||||
#endif
|
||||
|
||||
//postpone the queue initialization as kevent
|
||||
//do not pass kfd after fork()
|
||||
if (uwsgi.async > 1) {
|
||||
uwsgi_async_init();
|
||||
// a stack of unused cores
|
||||
uwsgi.async_queue_unused = uwsgi_malloc(sizeof(struct wsgi_request *) * uwsgi.async);
|
||||
|
||||
// fill it with default values
|
||||
for (i = 0; i < uwsgi.async; i++) {
|
||||
uwsgi.async_queue_unused[i] = &uwsgi.workers[uwsgi.mywid].cores[i].req;
|
||||
}
|
||||
|
||||
// the first available core is the last one
|
||||
uwsgi.async_queue_unused_ptr = uwsgi.async - 1;
|
||||
}
|
||||
|
||||
// setup UNIX signals for the worker
|
||||
@@ -3271,6 +3281,28 @@ void uwsgi_ignition() {
|
||||
}
|
||||
}
|
||||
|
||||
// mark the worker as "accepting" (this is a mark used by chain reloading)
|
||||
uwsgi.workers[uwsgi.mywid].accepting = 1;
|
||||
// ready to accept request, if i am a vassal signal Emperor about it
|
||||
if (uwsgi.has_emperor && uwsgi.mywid == 1) {
|
||||
char byte = 5;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("write()");
|
||||
}
|
||||
}
|
||||
|
||||
// run accepting hooks
|
||||
uwsgi_hooks_run(uwsgi.hook_accepting, "accepting", 1);
|
||||
if (uwsgi.workers[uwsgi.mywid].respawn_count == 1) {
|
||||
uwsgi_hooks_run(uwsgi.hook_accepting_once, "accepting-once", 1);
|
||||
}
|
||||
|
||||
if (uwsgi.mywid == 1) {
|
||||
uwsgi_hooks_run(uwsgi.hook_accepting1, "accepting1", 1);
|
||||
if (uwsgi.workers[uwsgi.mywid].respawn_count == 1) {
|
||||
uwsgi_hooks_run(uwsgi.hook_accepting1_once, "accepting1-once", 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.loop) {
|
||||
void (*u_loop) (void) = uwsgi_get_loop(uwsgi.loop);
|
||||
@@ -3718,7 +3750,7 @@ void uwsgi_opt_set_16bit(char *opt, char *value, void *key) {
|
||||
|
||||
void uwsgi_opt_set_megabytes(char *opt, char *value, void *key) {
|
||||
uint64_t *ptr = (uint64_t *) key;
|
||||
*ptr = (strtoul(value, NULL, 10)) * 1024 * 1024;
|
||||
*ptr = (uint64_t)strtoul(value, NULL, 10) * 1024 * 1024;
|
||||
}
|
||||
|
||||
void uwsgi_opt_set_dyn(char *opt, char *value, void *key) {
|
||||
@@ -4518,6 +4550,45 @@ void uwsgi_opt_dot_h(char *opt, char *filename, void *foobar) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
extern char *uwsgi_config_py;
|
||||
char *uwsgi_get_config_py() {
|
||||
char *src = uwsgi_config_py;
|
||||
size_t len = strlen(src);
|
||||
char *ptr = uwsgi_malloc(len / 2);
|
||||
char *base = ptr;
|
||||
size_t i;
|
||||
unsigned int u;
|
||||
for (i = 0; i < len; i += 2) {
|
||||
sscanf(src + i, "%2x", &u);
|
||||
*ptr++ = (char) u;
|
||||
}
|
||||
#ifdef UWSGI_ZLIB
|
||||
struct uwsgi_buffer *ub = uwsgi_zlib_decompress(base, ptr-base);
|
||||
if (!ub) {
|
||||
free(base);
|
||||
return "";
|
||||
}
|
||||
// add final null byte
|
||||
uwsgi_buffer_append(ub, "\0", 1);
|
||||
free(base);
|
||||
// base is the final blob
|
||||
base = ub->buf;
|
||||
ub->buf = NULL;
|
||||
uwsgi_buffer_destroy(ub);
|
||||
#endif
|
||||
return base;
|
||||
}
|
||||
|
||||
void uwsgi_opt_config_py(char *opt, char *filename, void *foobar) {
|
||||
fprintf(stdout, "%s\n", uwsgi_get_config_py());
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
void uwsgi_opt_build_plugin(char *opt, char *directory, void *foobar) {
|
||||
uwsgi_build_plugin(directory);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void uwsgi_opt_connect_and_read(char *opt, char *address, void *foobar) {
|
||||
|
||||
|
||||
+63
-11
@@ -10,9 +10,17 @@
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(10 + len);
|
||||
if (uwsgi_buffer_u8(ub, 0x81)) goto error;
|
||||
static struct uwsgi_buffer *uwsgi_websocket_message(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
|
||||
struct uwsgi_buffer *ub = wsgi_req->websocket_send_buf;
|
||||
if (!ub) {
|
||||
wsgi_req->websocket_send_buf = uwsgi_buffer_new(10 + len);
|
||||
ub = wsgi_req->websocket_send_buf;
|
||||
}
|
||||
else {
|
||||
// reset the buffer
|
||||
ub->pos = 0;
|
||||
}
|
||||
if (uwsgi_buffer_u8(ub, opcode)) goto error;
|
||||
if (len < 126) {
|
||||
if (uwsgi_buffer_u8(ub, len)) goto error;
|
||||
}
|
||||
@@ -29,7 +37,6 @@ static struct uwsgi_buffer *uwsgi_websocket_message(char *msg, size_t len) {
|
||||
return ub;
|
||||
|
||||
error:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -66,27 +73,72 @@ static int uwsgi_websockets_check_pingpong(struct wsgi_request *wsgi_req) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len) {
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_message(msg, len);
|
||||
static int uwsgi_websocket_send_do(struct wsgi_request *wsgi_req, char *msg, size_t len, uint8_t opcode) {
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, msg, len, opcode);
|
||||
if (!ub) return -1;
|
||||
|
||||
ssize_t ret = uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
uwsgi_buffer_destroy(ub);
|
||||
return ret;
|
||||
|
||||
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
}
|
||||
|
||||
static int uwsgi_websocket_send_from_sharedarea_do(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len, uint8_t opcode) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) return -1;
|
||||
if (!len) {
|
||||
len = sa->honour_used ? sa->used-pos : ((sa->max_pos+1)-pos);
|
||||
}
|
||||
uwsgi_rlock(sa->lock);
|
||||
sa->hits++;
|
||||
struct uwsgi_buffer *ub = uwsgi_websocket_message(wsgi_req, sa->area, len, opcode);
|
||||
uwsgi_rwunlock(sa->lock);
|
||||
if (!ub) return -1;
|
||||
|
||||
return uwsgi_response_write_body_do(wsgi_req, ub->buf, ub->pos);
|
||||
}
|
||||
|
||||
int uwsgi_websocket_send(struct wsgi_request *wsgi_req, char *msg, size_t len) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len);
|
||||
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len, 0x81);
|
||||
if (ret < 0) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_websocket_send_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x81);
|
||||
if (ret < 0) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_websocket_send_binary(struct wsgi_request *wsgi_req, char *msg, size_t len) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t ret = uwsgi_websocket_send_do(wsgi_req, msg, len, 0x82);
|
||||
if (ret < 0) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int uwsgi_websocket_send_binary_from_sharedarea(struct wsgi_request *wsgi_req, int id, uint64_t pos, uint64_t len) {
|
||||
if (wsgi_req->websocket_closed) {
|
||||
return -1;
|
||||
}
|
||||
ssize_t ret = uwsgi_websocket_send_from_sharedarea_do(wsgi_req, id, pos, len, 0x82);
|
||||
if (ret < 0) {
|
||||
wsgi_req->websocket_closed = 1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void uwsgi_websocket_parse_header(struct wsgi_request *wsgi_req) {
|
||||
uint8_t byte1 = wsgi_req->websocket_buf->buf[0];
|
||||
uint8_t byte2 = wsgi_req->websocket_buf->buf[1];
|
||||
|
||||
+244
-7
@@ -179,7 +179,7 @@ int uwsgi_response_add_header_force(struct wsgi_request *wsgi_req, char *key, ui
|
||||
return uwsgi_response_add_header_do(wsgi_req, key, key_len, value, value_len);
|
||||
}
|
||||
|
||||
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
static int uwsgi_response_write_headers_do0(struct wsgi_request *wsgi_req) {
|
||||
if (wsgi_req->headers_sent || !wsgi_req->headers || wsgi_req->response_size || wsgi_req->write_errors) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
@@ -209,11 +209,20 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
|
||||
if (wsgi_req->socket->proto_fix_headers(wsgi_req)) { wsgi_req->write_errors++ ; return -1;}
|
||||
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
|
||||
int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
|
||||
int ret = uwsgi_response_write_headers_do0(wsgi_req);
|
||||
if (ret != UWSGI_AGAIN) return ret;
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write_headers(wsgi_req, wsgi_req->headers->buf, wsgi_req->headers->pos);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_response_write_headers_do()");
|
||||
uwsgi_req_error("uwsgi_response_write_headers_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
@@ -221,6 +230,7 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
@@ -238,6 +248,100 @@ int uwsgi_response_write_headers_do(struct wsgi_request *wsgi_req) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
private function for highly optimized writes (1 single syscall for headers and body)
|
||||
*/
|
||||
static int uwsgi_response_writev_headers_and_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
struct iovec iov[2];
|
||||
|
||||
int ret = uwsgi_response_write_headers_do0(wsgi_req);
|
||||
if (ret != UWSGI_AGAIN) return ret;
|
||||
|
||||
iov[0].iov_base = wsgi_req->headers->buf;
|
||||
iov[0].iov_len = wsgi_req->headers->pos;
|
||||
iov[1].iov_base = buf;
|
||||
iov[1].iov_len = len;
|
||||
|
||||
size_t iov_len = 2;
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
// no need to use writev if a single iovec remains
|
||||
if (iov_len == 1) {
|
||||
buf = iov[0].iov_base;
|
||||
len = iov[0].iov_len;
|
||||
// update counters
|
||||
wsgi_req->headers_size += wsgi_req->headers->pos;
|
||||
wsgi_req->headers_sent = 1;
|
||||
wsgi_req->response_size += wsgi_req->write_pos - wsgi_req->headers_size;
|
||||
wsgi_req->write_pos = 0;
|
||||
goto fallback;
|
||||
}
|
||||
int ret = wsgi_req->socket->proto_writev(wsgi_req, iov, &iov_len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("uwsgi_response_writev_headers_and_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_writev_headers_and_body_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->headers_size += wsgi_req->headers->pos;
|
||||
wsgi_req->response_size += len;
|
||||
wsgi_req->headers_sent = 1;
|
||||
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
return UWSGI_OK;
|
||||
|
||||
fallback:
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
// here we use the parent name
|
||||
uwsgi_req_error("uwsgi_response_write_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
// here we use the parent name
|
||||
uwsgi_log("uwsgi_response_write_body_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
wsgi_req->response_size += wsgi_req->write_pos;
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
return UWSGI_OK;
|
||||
|
||||
}
|
||||
|
||||
// this is the function called by all request plugins to send chunks to the client
|
||||
int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
|
||||
@@ -278,6 +382,9 @@ int uwsgi_response_write_body_do(struct wsgi_request *wsgi_req, char *buf, size_
|
||||
write:
|
||||
// send headers if not already sent
|
||||
if (!wsgi_req->headers_sent) {
|
||||
if (wsgi_req->socket->proto_writev && len > 0 && wsgi_req->headers) {
|
||||
return uwsgi_response_writev_headers_and_body_do(wsgi_req, buf, len);
|
||||
}
|
||||
int ret = uwsgi_response_write_headers_do(wsgi_req);
|
||||
if (ret == UWSGI_OK) goto sendbody;
|
||||
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
|
||||
@@ -290,10 +397,11 @@ sendbody:
|
||||
if (len == 0) return UWSGI_OK;
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_response_write_body_do()");
|
||||
uwsgi_req_error("uwsgi_response_write_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
@@ -301,6 +409,7 @@ sendbody:
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
@@ -317,6 +426,130 @@ sendbody:
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
int uwsgi_response_writev_body_do(struct wsgi_request *wsgi_req, struct iovec *iov, size_t len) {
|
||||
|
||||
if (wsgi_req->write_errors) return -1;
|
||||
if (wsgi_req->ignore_body) return UWSGI_OK;
|
||||
|
||||
#ifdef UWSGI_ROUTING
|
||||
// special case here, we could need to set transformations before
|
||||
if (!wsgi_req->headers_sent) {
|
||||
// apply response routes
|
||||
if (uwsgi_apply_response_routes(wsgi_req) == UWSGI_ROUTE_BREAK) {
|
||||
// from now on ignore write body requests...
|
||||
wsgi_req->ignore_body = 1;
|
||||
return -1;
|
||||
}
|
||||
wsgi_req->is_response_routing = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t i;
|
||||
int buffering = 0;
|
||||
// transformations apply to every vector
|
||||
for(i=0;i<len;i++) {
|
||||
// if the transformation chain returns 1, we are in buffering mode
|
||||
if (wsgi_req->transformed_chunk_len == 0 && wsgi_req->transformations) {
|
||||
int t_ret = uwsgi_apply_transformations(wsgi_req, iov[i].iov_base, iov[i].iov_len);
|
||||
if (t_ret == 0) {
|
||||
iov[i].iov_base = wsgi_req->transformed_chunk;
|
||||
iov[i].iov_len = wsgi_req->transformed_chunk_len;
|
||||
// reset transformation
|
||||
wsgi_req->transformed_chunk = NULL;
|
||||
wsgi_req->transformed_chunk_len = 0;
|
||||
goto write;
|
||||
}
|
||||
if (t_ret == 1) {
|
||||
buffering = 1;
|
||||
continue;
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (buffering) return UWSGI_OK;
|
||||
|
||||
write:
|
||||
// send headers if not already sent
|
||||
if (!wsgi_req->headers_sent) {
|
||||
int ret = uwsgi_response_write_headers_do(wsgi_req);
|
||||
if (ret == UWSGI_OK) goto sendbody;
|
||||
if (ret == UWSGI_AGAIN) return UWSGI_AGAIN;
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
|
||||
sendbody:
|
||||
|
||||
if (len == 0) return UWSGI_OK;
|
||||
// unfortunately vector based I/O cannot be accomplished on all protocols
|
||||
if (!wsgi_req->socket->proto_writev) goto fallback;
|
||||
|
||||
// we use a copy to avoid mess
|
||||
size_t iov_len = len;
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_writev(wsgi_req, iov, &iov_len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("uwsgi_response_writev_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_writev_body_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
goto done;
|
||||
|
||||
fallback:
|
||||
|
||||
for(i=0;i<len;i++) {
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, iov[i].iov_base, iov[i].iov_len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_req_error("uwsgi_response_writev_body_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
uwsgi_log("uwsgi_response_writev_body_do() TIMEOUT !!!\n");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
wsgi_req->response_size += wsgi_req->write_pos;
|
||||
// reset for the next write
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
|
||||
int uwsgi_response_sendfile_do(struct wsgi_request *wsgi_req, int fd, size_t pos, size_t len) {
|
||||
return uwsgi_response_sendfile_do_can_close(wsgi_req, fd, pos, len, 1);
|
||||
}
|
||||
@@ -349,7 +582,7 @@ sendfile:
|
||||
if (len == 0) {
|
||||
struct stat st;
|
||||
if (fstat(fd, &st)) {
|
||||
uwsgi_error("uwsgi_response_sendfile_do()/fstat()");
|
||||
uwsgi_req_error("uwsgi_response_sendfile_do()/fstat()");
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
return -1;
|
||||
@@ -367,7 +600,7 @@ sendfile:
|
||||
if (!can_close) {
|
||||
int tmp_fd = dup(fd);
|
||||
if (tmp_fd < 0) {
|
||||
uwsgi_error("uwsgi_response_sendfile_do()/dup()");
|
||||
uwsgi_req_error("uwsgi_response_sendfile_do()/dup()");
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
}
|
||||
@@ -388,10 +621,11 @@ sendfile:
|
||||
wsgi_req->via = UWSGI_VIA_SENDFILE;
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_sendfile(wsgi_req, fd, pos, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_response_sendfile_do()");
|
||||
uwsgi_req_error("uwsgi_response_sendfile_do()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
if (can_close) close(fd);
|
||||
@@ -400,6 +634,7 @@ sendfile:
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) {
|
||||
wsgi_req->write_errors++;
|
||||
@@ -454,10 +689,11 @@ int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
wsgi_req->write_pos = 0;
|
||||
|
||||
for(;;) {
|
||||
errno = 0;
|
||||
int ret = wsgi_req->socket->proto_write(wsgi_req, buf, len);
|
||||
if (ret < 0) {
|
||||
if (!uwsgi.ignore_write_errors) {
|
||||
uwsgi_error("uwsgi_simple_write()");
|
||||
uwsgi_req_error("uwsgi_simple_write()");
|
||||
}
|
||||
wsgi_req->write_errors++;
|
||||
return -1;
|
||||
@@ -465,6 +701,7 @@ int uwsgi_simple_write(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
if (ret == UWSGI_OK) {
|
||||
break;
|
||||
}
|
||||
if (!uwsgi_is_again()) continue;
|
||||
ret = uwsgi_wait_write_req(wsgi_req);
|
||||
if (ret < 0) { wsgi_req->write_errors++; return -1;}
|
||||
if (ret == 0) {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import uwsgi
|
||||
|
||||
import os
|
||||
|
||||
def application(env, start_response):
|
||||
@@ -15,12 +14,12 @@ def application(env, start_response):
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
yield "--%s\n" % boundary
|
||||
yield "--%s\r\n" % boundary
|
||||
|
||||
while 1:
|
||||
yield "Content-Type: image/jpeg\r\n\r\n"
|
||||
uwsgi.sendfile('screenshot.jpg')
|
||||
yield "--%s\n" % boundary
|
||||
print os.system('screencapture -t jpg -m -T 1 screenshot.jpg')
|
||||
f = open('screenshot.jpg')
|
||||
yield env['wsgi.file_wrapper'](f)
|
||||
yield "\r\n--%s\r\n" % boundary
|
||||
#os.system('./isightcapture -w 640 -h 480 screenshot.jpg')
|
||||
#os.system('screencapture -m -T 1 screenshot.jpg')
|
||||
|
||||
+6
-1
@@ -52,6 +52,11 @@ int uwsgi_is_a_keep_mount(char *mp) {
|
||||
|
||||
}
|
||||
|
||||
static int uwsgi_ns_start(void *v_argv) {
|
||||
uwsgi_start(v_argv);
|
||||
return uwsgi_run();
|
||||
}
|
||||
|
||||
void linux_namespace_start(void *argv) {
|
||||
for (;;) {
|
||||
char stack[PTHREAD_STACK_MIN];
|
||||
@@ -61,7 +66,7 @@ void linux_namespace_start(void *argv) {
|
||||
if (uwsgi.ns_net) {
|
||||
clone_flags |= CLONE_NEWNET;
|
||||
}
|
||||
pid_t pid = clone(uwsgi_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
|
||||
pid_t pid = clone(uwsgi_ns_start, stack + PTHREAD_STACK_MIN, clone_flags, (void *) argv);
|
||||
if (pid == -1) {
|
||||
uwsgi_error("clone()");
|
||||
exit(1);
|
||||
|
||||
@@ -65,6 +65,33 @@ SV * coroae_coro_new(CV *block) {
|
||||
return newobj;
|
||||
}
|
||||
|
||||
static int coroae_wait_milliseconds(int timeout) {
|
||||
int ret = -1;
|
||||
dSP;
|
||||
ENTER;
|
||||
SAVETMPS;
|
||||
PUSHMARK(SP);
|
||||
XPUSHs(newSVnv(((double)timeout)/1000.0));
|
||||
PUTBACK;
|
||||
call_pv("Coro::AnyEvent::sleep", G_SCALAR);
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("[uwsgi-perl error] %s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
SV *p_ret = POPs;
|
||||
if (SvTRUE(p_ret)) {
|
||||
ret = 0;
|
||||
}
|
||||
}
|
||||
PUTBACK;
|
||||
FREETMPS;
|
||||
LEAVE;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int coroae_wait_fd_read(int fd, int timeout) {
|
||||
int ret = 0;
|
||||
dSP;
|
||||
@@ -377,6 +404,7 @@ static void coroae_loop() {
|
||||
uwsgi.current_wsgi_req = coroae_current_wsgi_req;
|
||||
uwsgi.wait_write_hook = coroae_wait_fd_write;
|
||||
uwsgi.wait_read_hook = coroae_wait_fd_read;
|
||||
uwsgi.wait_milliseconds_hook = coroae_wait_milliseconds;
|
||||
|
||||
I_CORO_API("uwsgi::coroae");
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ if not coroapi:
|
||||
|
||||
NAME='coroae'
|
||||
CFLAGS = os.popen('perl -MExtUtils::Embed -e ccopts').read().rstrip().split()
|
||||
CFLAGS += ['-Wno-int-to-pointer-cast', '-Wno-error=int-to-pointer-cast', '-I%s/Coro' % coroapi]
|
||||
CFLAGS += ['-Wno-int-to-pointer-cast', '-Wno-error=format', '-Wno-error=int-to-pointer-cast', '-I%s/Coro' % coroapi]
|
||||
LDFLAGS = []
|
||||
LIBS = []
|
||||
|
||||
|
||||
@@ -52,9 +52,7 @@ s.send_multipart(['touch','foo.ini',"[uwsgi]\nsocket=:4142"])
|
||||
|
||||
*/
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
|
||||
#include "../../uwsgi.h"
|
||||
#include <uwsgi.h>
|
||||
#include <zmq.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
@@ -215,7 +213,11 @@ static void uwsgi_imperial_monitor_zeromq_event(struct uwsgi_emperor_scanner *ue
|
||||
// initialize the zmq PULL socket
|
||||
static void uwsgi_imperial_monitor_zeromq_init(struct uwsgi_emperor_scanner *ues) {
|
||||
|
||||
void *context = uwsgi_zeromq_init();
|
||||
void *context = zmq_init(1);
|
||||
if (!context) {
|
||||
uwsgi_error("uwsgi_imperial_monitor_zeromq_init()/zmq_init()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ues->data = zmq_socket(context, ZMQ_PULL);
|
||||
if (!ues->data) {
|
||||
@@ -256,7 +258,3 @@ struct uwsgi_plugin emperor_zeromq_plugin = {
|
||||
.name = "emperor_zeromq",
|
||||
.on_load = emperor_zeromq_init,
|
||||
};
|
||||
|
||||
#else
|
||||
#error the uWSGI ZeroMQ imperial monitor requires uWSGI zeromq support
|
||||
#endif
|
||||
|
||||
@@ -361,6 +361,7 @@ static void gevent_loop() {
|
||||
|
||||
uwsgi.wait_write_hook = uwsgi_gevent_wait_write_hook;
|
||||
uwsgi.wait_read_hook = uwsgi_gevent_wait_read_hook;
|
||||
uwsgi.wait_milliseconds_hook = uwsgi_gevent_wait_milliseconds_hook;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
int uwsgi_gevent_wait_write_hook(int, int);
|
||||
int uwsgi_gevent_wait_read_hook(int, int);
|
||||
int uwsgi_gevent_wait_milliseconds_hook(int);
|
||||
|
||||
#define GEVENT_SWITCH PyObject *gswitch = python_call(ugevent.greenlet_switch, ugevent.greenlet_switch_args, 0, NULL); Py_DECREF(gswitch)
|
||||
#define GET_CURRENT_GREENLET python_call(ugevent.get_current, ugevent.get_current_args, 0, NULL)
|
||||
|
||||
@@ -98,3 +98,42 @@ int uwsgi_gevent_wait_read_hook(int fd, int timeout) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uwsgi_gevent_wait_milliseconds_hook(int timeout) {
|
||||
|
||||
PyObject *ret = NULL;
|
||||
|
||||
PyObject *timer = PyObject_CallMethod(ugevent.hub_loop, "timer", "f", ((double) timeout)/1000.0);
|
||||
if (!timer) return -1;
|
||||
|
||||
PyObject *current_greenlet = GET_CURRENT_GREENLET;
|
||||
PyObject *current = PyObject_GetAttrString(current_greenlet, "switch");
|
||||
|
||||
ret = PyObject_CallMethod(timer, "start", "OO", current, timer);
|
||||
if (!ret) {
|
||||
Py_DECREF(current); Py_DECREF(current_greenlet);
|
||||
Py_DECREF(timer);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
ret = PyObject_CallMethod(ugevent.hub, "switch", NULL);
|
||||
if (!ret) {
|
||||
ret = PyObject_CallMethod(timer, "stop", NULL);
|
||||
if (ret) { Py_DECREF(ret); }
|
||||
Py_DECREF(current); Py_DECREF(current_greenlet);
|
||||
Py_DECREF(timer);
|
||||
return -1;
|
||||
}
|
||||
Py_DECREF(ret);
|
||||
|
||||
if (ret == timer) {
|
||||
ret = PyObject_CallMethod(timer, "stop", NULL);
|
||||
if (ret) { Py_DECREF(ret); }
|
||||
Py_DECREF(current); Py_DECREF(current_greenlet);
|
||||
Py_DECREF(timer);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
#include <uwsgi.h>
|
||||
#include <zmq.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
static struct uwsgi_option uwsgi_zmq_logger_options[] = {
|
||||
{"log-zeromq", required_argument, 0, "send logs to a zeromq server", uwsgi_opt_set_logger, "zeromq", UWSGI_OPT_MASTER | UWSGI_OPT_LOG_MASTER},
|
||||
{NULL, 0, 0, NULL, NULL, NULL, 0},
|
||||
};
|
||||
|
||||
// the zeromq logger
|
||||
static ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *ul, char *message, size_t len) {
|
||||
|
||||
if (!ul->configured) {
|
||||
|
||||
if (!ul->arg) {
|
||||
uwsgi_log_safe("invalid zeromq syntax\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *ctx = zmq_init(1);
|
||||
if (!ctx) exit(1);
|
||||
|
||||
ul->data = zmq_socket(ctx, ZMQ_PUSH);
|
||||
if (ul->data == NULL) {
|
||||
uwsgi_error_safe("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (zmq_connect(ul->data, ul->arg) < 0) {
|
||||
uwsgi_error_safe("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ul->configured = 1;
|
||||
}
|
||||
|
||||
zmq_msg_t msg;
|
||||
if (zmq_msg_init_size(&msg, len) == 0) {
|
||||
memcpy(zmq_msg_data(&msg), message, len);
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
zmq_sendmsg(ul->data, &msg, 0);
|
||||
#else
|
||||
zmq_send(ul->data, &msg, 0);
|
||||
#endif
|
||||
zmq_msg_close(&msg);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void uwsgi_zmq_logger_register() {
|
||||
uwsgi_register_logger("zmq", uwsgi_zeromq_logger);
|
||||
uwsgi_register_logger("zeromq", uwsgi_zeromq_logger);
|
||||
}
|
||||
|
||||
struct uwsgi_plugin logzmq_plugin = {
|
||||
.name = "logzmq",
|
||||
.options = uwsgi_zmq_logger_options,
|
||||
.on_load = uwsgi_zmq_logger_register,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='logzmq'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lzmq']
|
||||
|
||||
GCC_LIST = ['plugin']
|
||||
@@ -1,39 +1,21 @@
|
||||
/*
|
||||
|
||||
generic ZeroMQ functions + Mongrel2 protocol parser
|
||||
Mongrel2 protocol parser
|
||||
|
||||
*/
|
||||
|
||||
#include <uwsgi.h>
|
||||
#include <zmq.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void *uwsgi_zeromq_init() {
|
||||
if (!uwsgi.zmq_context) {
|
||||
uwsgi.zmq_context = zmq_init(1);
|
||||
if (uwsgi.zmq_context == NULL) {
|
||||
uwsgi_error("zmq_init()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
return uwsgi.zmq_context;
|
||||
}
|
||||
|
||||
void uwsgi_zeromq_init_sockets() {
|
||||
|
||||
uwsgi_zeromq_init();
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
if (!uwsgi_sock->proto_name || strcmp(uwsgi_sock->proto_name, "zmq")) {
|
||||
goto zmq_next;
|
||||
}
|
||||
uwsgi_proto_zeromq_setup(uwsgi_sock);
|
||||
zmq_next:
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
static struct uwsgi_option mongrel2_options[] = {
|
||||
{"zeromq", required_argument, 0, "create a mongrel2/zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "mongrel2", 0},
|
||||
{"zmq", required_argument, 0, "create a mongrel2/zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "mongrel2", 0},
|
||||
{"zeromq-socket", required_argument, 0, "create a mongrel2/zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "mongrel2", 0},
|
||||
{"zmq-socket", required_argument, 0, "create a mongrel2/zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "mongrel2", 0},
|
||||
{"mongrel2", required_argument, 0, "create a mongrel2/zeromq pub/sub pair", uwsgi_opt_add_lazy_socket, "mongrel2", 0},
|
||||
};
|
||||
|
||||
#ifdef UWSGI_JSON
|
||||
#include <jansson.h>
|
||||
@@ -290,7 +272,7 @@ int uwsgi_proto_zeromq_parser(struct wsgi_request *wsgi_req) {
|
||||
|
||||
void uwsgi_proto_zeromq_thread_fixup(struct uwsgi_socket *uwsgi_sock, int async_id) {
|
||||
|
||||
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
|
||||
void *tmp_zmq_pull = zmq_socket(uwsgi_sock->ctx, ZMQ_PULL);
|
||||
if (tmp_zmq_pull == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
@@ -315,7 +297,7 @@ void uwsgi_proto_zeromq_thread_fixup(struct uwsgi_socket *uwsgi_sock, int async_
|
||||
#endif
|
||||
}
|
||||
|
||||
// fake function, the bosy is i na file or completely in memory
|
||||
// fake function, the body is in a file or completely in memory
|
||||
ssize_t uwsgi_proto_zeromq_read_body(struct wsgi_request *wsgi_req, char *buf, size_t len) {
|
||||
return 0;
|
||||
}
|
||||
@@ -565,38 +547,6 @@ int uwsgi_proto_zeromq_sendfile(struct wsgi_request *wsgi_req, int fd, size_t po
|
||||
|
||||
void uwsgi_proto_zeromq_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
|
||||
char *responder = strchr(uwsgi_sock->name, ',');
|
||||
if (!responder) {
|
||||
uwsgi_log("invalid zeromq address\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_sock->receiver = uwsgi_concat2n(uwsgi_sock->name, responder - uwsgi_sock->name, "", 0);
|
||||
responder++;
|
||||
|
||||
uwsgi_sock->pub = zmq_socket(uwsgi.zmq_context, ZMQ_PUB);
|
||||
if (uwsgi_sock->pub == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
// generate uuid
|
||||
uuid_t uuid_zmq;
|
||||
uuid_generate(uuid_zmq);
|
||||
uuid_unparse(uuid_zmq, uwsgi_sock->uuid);
|
||||
|
||||
if (zmq_setsockopt(uwsgi_sock->pub, ZMQ_IDENTITY, uwsgi_sock->uuid, 36) < 0) {
|
||||
uwsgi_error("zmq_setsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (zmq_connect(uwsgi_sock->pub, responder) < 0) {
|
||||
uwsgi_error("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("zeromq UUID for responder %s on worker %d: %.*s\n", responder, uwsgi.mywid, 36, uwsgi_sock->uuid);
|
||||
|
||||
uwsgi_sock->proto = uwsgi_proto_zeromq_parser;
|
||||
uwsgi_sock->proto_accept = uwsgi_proto_zeromq_accept;
|
||||
uwsgi_sock->proto_prepare_headers = uwsgi_proto_base_prepare_headers;
|
||||
@@ -614,55 +564,105 @@ void uwsgi_proto_zeromq_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
uwsgi_sock->retry = uwsgi_malloc(sizeof(int) * uwsgi.threads);
|
||||
uwsgi_sock->retry[0] = 1;
|
||||
|
||||
// inform loop engine about edge trigger status
|
||||
uwsgi.is_et = 1;
|
||||
uwsgi_sock->fd = -1;
|
||||
}
|
||||
|
||||
static void uwsgi_proto_mongrel2_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
};
|
||||
|
||||
static void mongrel2_register_proto() {
|
||||
uwsgi_register_protocol("mongrel2", uwsgi_proto_mongrel2_setup);
|
||||
}
|
||||
|
||||
static void mongrel2_connect() {
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
while(uwsgi_sock) {
|
||||
uwsgi_sock->ctx = zmq_init(1);
|
||||
if (!uwsgi_sock->ctx) {
|
||||
uwsgi_error("mongrel2_connect()/zmq_init()");
|
||||
exit(1);
|
||||
}
|
||||
char *responder = strchr(uwsgi_sock->name, ',');
|
||||
if (!responder) {
|
||||
uwsgi_log("invalid zeromq address\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_sock->receiver = uwsgi_concat2n(uwsgi_sock->name, responder - uwsgi_sock->name, "", 0);
|
||||
responder++;
|
||||
|
||||
uwsgi_sock->pub = zmq_socket(uwsgi_sock->ctx, ZMQ_PUB);
|
||||
if (uwsgi_sock->pub == NULL) {
|
||||
uwsgi_error("mongrel2_connect()/zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
// generate uuid
|
||||
uwsgi_uuid(uwsgi_sock->uuid);
|
||||
|
||||
if (zmq_setsockopt(uwsgi_sock->pub, ZMQ_IDENTITY, uwsgi_sock->uuid, 36) < 0) {
|
||||
uwsgi_error("mongrel2_connect()/zmq_setsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (zmq_connect(uwsgi_sock->pub, responder) < 0) {
|
||||
uwsgi_error("mongrel2_connect()/zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
uwsgi_log("zeromq UUID for responder %s on worker %d: %.*s\n", responder, uwsgi.mywid, 36, uwsgi_sock->uuid);
|
||||
|
||||
// inform loop engine about edge trigger status
|
||||
uwsgi.is_et = 1;
|
||||
|
||||
|
||||
// initialize a lock for multithread usage
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_init(&uwsgi_sock->lock, NULL);
|
||||
}
|
||||
// initialize a lock for multithread usage
|
||||
if (uwsgi.threads > 1) {
|
||||
pthread_mutex_init(&uwsgi_sock->lock, NULL);
|
||||
}
|
||||
|
||||
// one pull per-thread
|
||||
if (pthread_key_create(&uwsgi_sock->key, NULL)) {
|
||||
uwsgi_error("pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
// one pull per-thread
|
||||
if (pthread_key_create(&uwsgi_sock->key, NULL)) {
|
||||
uwsgi_error("mongrel2_connect()/pthread_key_create()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void *tmp_zmq_pull = zmq_socket(uwsgi.zmq_context, ZMQ_PULL);
|
||||
if (tmp_zmq_pull == NULL) {
|
||||
uwsgi_error("zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
if (zmq_connect(tmp_zmq_pull, uwsgi_sock->receiver) < 0) {
|
||||
uwsgi_error("zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
void *tmp_zmq_pull = zmq_socket(uwsgi_sock->ctx, ZMQ_PULL);
|
||||
if (tmp_zmq_pull == NULL) {
|
||||
uwsgi_error("mongrel2_connect()/zmq_socket()");
|
||||
exit(1);
|
||||
}
|
||||
if (zmq_connect(tmp_zmq_pull, uwsgi_sock->receiver) < 0) {
|
||||
uwsgi_error("mongrel2_connect()/zmq_connect()");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
pthread_setspecific(uwsgi_sock->key, tmp_zmq_pull);
|
||||
pthread_setspecific(uwsgi_sock->key, tmp_zmq_pull);
|
||||
|
||||
#ifdef ZMQ_FD
|
||||
size_t zmq_socket_len = sizeof(int);
|
||||
if (zmq_getsockopt(pthread_getspecific(uwsgi_sock->key), ZMQ_FD, &uwsgi_sock->fd, &zmq_socket_len) < 0) {
|
||||
uwsgi_error("zmq_getsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi_sock->fd_threads = uwsgi_malloc(sizeof(int) * uwsgi.threads);
|
||||
uwsgi_sock->fd_threads[0] = uwsgi_sock->fd;
|
||||
}
|
||||
#else
|
||||
uwsgi_sock->fd = -1;
|
||||
size_t zmq_socket_len = sizeof(int);
|
||||
if (zmq_getsockopt(pthread_getspecific(uwsgi_sock->key), ZMQ_FD, &uwsgi_sock->fd, &zmq_socket_len) < 0) {
|
||||
uwsgi_error("mongrel2_connect()/zmq_getsockopt()");
|
||||
exit(1);
|
||||
}
|
||||
if (uwsgi.threads > 1) {
|
||||
uwsgi_sock->fd_threads = uwsgi_malloc(sizeof(int) * uwsgi.threads);
|
||||
uwsgi_sock->fd_threads[0] = uwsgi_sock->fd;
|
||||
}
|
||||
#endif
|
||||
|
||||
uwsgi_sock->bound = 1;
|
||||
uwsgi_sock->bound = 1;
|
||||
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
|
||||
uwsgi_sock->recv_flag = ZMQ_DONTWAIT;
|
||||
uwsgi_sock->recv_flag = ZMQ_DONTWAIT;
|
||||
#else
|
||||
uwsgi_sock->recv_flag = ZMQ_NOBLOCK;
|
||||
uwsgi_sock->recv_flag = ZMQ_NOBLOCK;
|
||||
#endif
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
}
|
||||
|
||||
void uwsgi_proto_zmq_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
uwsgi.zeromq = 1;
|
||||
}
|
||||
struct uwsgi_plugin mongrel2_plugin = {
|
||||
.name = "mongrel2",
|
||||
.options = mongrel2_options,
|
||||
.post_fork = mongrel2_connect,
|
||||
.on_load = mongrel2_register_proto,
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
NAME='mongrel2'
|
||||
CFLAGS = []
|
||||
LDFLAGS = []
|
||||
LIBS = ['-lzmq']
|
||||
|
||||
GCC_LIST = ['mongrel2']
|
||||
@@ -149,7 +149,7 @@ XS(XS_streaming_write) {
|
||||
|
||||
uwsgi_response_write_body_do(wsgi_req, body, blen);
|
||||
uwsgi_pl_check_write_errors {
|
||||
// noop
|
||||
croak("error while streaming PSGI response");
|
||||
}
|
||||
|
||||
XSRETURN(0);
|
||||
|
||||
@@ -194,9 +194,12 @@ int uwsgi_perl_obj_can(SV *obj, char *method, size_t len) {
|
||||
XPUSHs(sv_2mortal(newSVpv(method, len)));
|
||||
PUTBACK;
|
||||
|
||||
call_method( "can", G_SCALAR);
|
||||
call_method( "can", G_SCALAR|G_EVAL);
|
||||
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
|
||||
ret = SvROK(POPs);
|
||||
PUTBACK;
|
||||
@@ -253,7 +256,7 @@ SV *uwsgi_perl_obj_call(SV *obj, char *method) {
|
||||
|
||||
SPAGAIN;
|
||||
if(SvTRUE(ERRSV)) {
|
||||
uwsgi_log("%s\n", SvPV_nolen(ERRSV));
|
||||
uwsgi_log("%s", SvPV_nolen(ERRSV));
|
||||
}
|
||||
else {
|
||||
ret = SvREFCNT_inc(POPs);
|
||||
|
||||
@@ -22,15 +22,13 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
if (wsgi_req->async_force_again) {
|
||||
SvREFCNT_dec(chunk);
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
|
||||
chitem = SvPV( chunk, hlen);
|
||||
|
||||
if (hlen <= 0) {
|
||||
SvREFCNT_dec(chunk);
|
||||
if (wsgi_req->async_force_again) {
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
SV *closed = uwsgi_perl_obj_call(wsgi_req->async_placeholder, "close");
|
||||
if (closed) {
|
||||
SvREFCNT_dec(closed);
|
||||
@@ -102,41 +100,40 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
}
|
||||
|
||||
if (!SvRV(*hitem)) { uwsgi_log("invalid PSGI response body\n") ; return UWSGI_OK; }
|
||||
|
||||
if (!SvROK(*hitem)) goto unsupported;
|
||||
|
||||
if (SvTYPE(SvRV(*hitem)) == SVt_PVGV || SvTYPE(SvRV(*hitem)) == SVt_PVHV || SvTYPE(SvRV(*hitem)) == SVt_PVMG) {
|
||||
|
||||
// respond to fileno ?
|
||||
if (uwsgi.async < 2) {
|
||||
// check for fileno() method, IO class or GvIO
|
||||
if (uwsgi_perl_obj_can(*hitem, "fileno", 6) || uwsgi_perl_obj_isa(*hitem, "IO") || (uwsgi_perl_obj_isa(*hitem, "GLOB") && GvIO(SvRV(*hitem))) ) {
|
||||
SV *fn = uwsgi_perl_obj_call(*hitem, "fileno");
|
||||
if (fn) {
|
||||
if (SvTYPE(fn) == SVt_IV && SvIV(fn) >= 0) {
|
||||
wsgi_req->sendfile_fd = SvIV(fn);
|
||||
SvREFCNT_dec(fn);
|
||||
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
|
||||
// no need to close here as perl GC will do the close()
|
||||
uwsgi_pl_check_write_errors {
|
||||
// noop
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
// check for fileno() method, IO class or GvIO
|
||||
if (uwsgi_perl_obj_can(*hitem, "fileno", 6) || uwsgi_perl_obj_isa(*hitem, "IO") || (uwsgi_perl_obj_isa(*hitem, "GLOB") && GvIO(SvRV(*hitem))) ) {
|
||||
SV *fn = uwsgi_perl_obj_call(*hitem, "fileno");
|
||||
if (fn) {
|
||||
if (SvTYPE(fn) == SVt_IV && SvIV(fn) >= 0) {
|
||||
wsgi_req->sendfile_fd = SvIV(fn);
|
||||
SvREFCNT_dec(fn);
|
||||
uwsgi_response_sendfile_do(wsgi_req, wsgi_req->sendfile_fd, 0, 0);
|
||||
// no need to close here as perl GC will do the close()
|
||||
uwsgi_pl_check_write_errors {
|
||||
// noop
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
SvREFCNT_dec(fn);
|
||||
}
|
||||
}
|
||||
|
||||
// check for path method
|
||||
if (uwsgi_perl_obj_can(*hitem, "path", 4)) {
|
||||
SV *p = uwsgi_perl_obj_call(*hitem, "path");
|
||||
int fd = open(SvPV_nolen(p), O_RDONLY);
|
||||
SvREFCNT_dec(p);
|
||||
// the following function will close fd
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0);
|
||||
uwsgi_pl_check_write_errors {
|
||||
// noop
|
||||
}
|
||||
return UWSGI_OK;
|
||||
// check for path method
|
||||
if (uwsgi_perl_obj_can(*hitem, "path", 4)) {
|
||||
SV *p = uwsgi_perl_obj_call(*hitem, "path");
|
||||
int fd = open(SvPV_nolen(p), O_RDONLY);
|
||||
SvREFCNT_dec(p);
|
||||
// the following function will close fd
|
||||
uwsgi_response_sendfile_do(wsgi_req, fd, 0, 0);
|
||||
uwsgi_pl_check_write_errors {
|
||||
// noop
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
for(;;) {
|
||||
@@ -149,13 +146,12 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
}
|
||||
|
||||
chitem = SvPV( chunk, hlen);
|
||||
if (uwsgi.async > 1 && wsgi_req->async_force_again) {
|
||||
SvREFCNT_dec(chunk);
|
||||
wsgi_req->async_placeholder = (SV *) *hitem;
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
if (hlen <= 0) {
|
||||
SvREFCNT_dec(chunk);
|
||||
if (uwsgi.async > 1 && wsgi_req->async_force_again) {
|
||||
wsgi_req->async_placeholder = (SV *) *hitem;
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -194,6 +190,7 @@ int psgi_response(struct wsgi_request *wsgi_req, AV *response) {
|
||||
|
||||
}
|
||||
else {
|
||||
unsupported:
|
||||
uwsgi_log("unsupported response body type: %d\n", SvTYPE(SvRV(*hitem)));
|
||||
}
|
||||
|
||||
|
||||
@@ -498,6 +498,70 @@ XS(XS_websocket_send) {
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_websocket_send_from_sharedarea) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(2);
|
||||
int id = SvIV(ST(0));
|
||||
uint64_t pos = SvIV(ST(1));
|
||||
uint64_t len = 0;
|
||||
|
||||
if (items > 2) {
|
||||
len = SvIV(ST(2));
|
||||
}
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (uwsgi_websocket_send_from_sharedarea(wsgi_req, id, pos, len)) {
|
||||
croak("unable to send websocket message from sharedarea");
|
||||
}
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
|
||||
XS(XS_websocket_send_binary) {
|
||||
dXSARGS;
|
||||
|
||||
char *message = NULL;
|
||||
STRLEN message_len = 0;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
message = SvPV(ST(0), message_len);
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (uwsgi_websocket_send_binary(wsgi_req, message, message_len)) {
|
||||
croak("unable to send websocket binary message");
|
||||
}
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XS(XS_websocket_send_binary_from_sharedarea) {
|
||||
dXSARGS;
|
||||
|
||||
psgi_check_args(2);
|
||||
int id = SvIV(ST(0));
|
||||
uint64_t pos = SvIV(ST(1));
|
||||
uint64_t len = 0;
|
||||
|
||||
if (items > 2) {
|
||||
len = SvIV(ST(2));
|
||||
}
|
||||
|
||||
struct wsgi_request *wsgi_req = current_wsgi_req();
|
||||
|
||||
if (uwsgi_websocket_send_binary_from_sharedarea(wsgi_req, id, pos, len)) {
|
||||
croak("unable to send websocket binary message from sharedarea");
|
||||
}
|
||||
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
|
||||
|
||||
XS(XS_websocket_recv) {
|
||||
dXSARGS;
|
||||
|
||||
@@ -668,6 +732,106 @@ XS(XS_metric_get) {
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_sharedarea_wait) {
|
||||
dXSARGS;
|
||||
int id;
|
||||
int freq = 0;
|
||||
int timeout = 0;
|
||||
|
||||
psgi_check_args(1);
|
||||
|
||||
id = SvIV(ST(0));
|
||||
if (items > 1) {
|
||||
freq = SvIV(ST(1));
|
||||
}
|
||||
|
||||
if (uwsgi_sharedarea_wait(id, freq, timeout)) {
|
||||
croak("unable to wait for sharedarea %d", id);
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
XS(XS_sharedarea_read) {
|
||||
dXSARGS;
|
||||
int id;
|
||||
uint64_t pos;
|
||||
uint64_t len = 0;
|
||||
psgi_check_args(2);
|
||||
|
||||
id = SvIV(ST(0));
|
||||
pos = SvIV(ST(1));
|
||||
|
||||
if (items > 2) {
|
||||
len = SvIV(ST(2));
|
||||
}
|
||||
else {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) {
|
||||
croak("unable to read from sharedarea %d", id);
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
len = (sa->max_pos+1)-pos;
|
||||
}
|
||||
|
||||
char *buf = uwsgi_malloc(len);
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, buf, len);
|
||||
if (rlen < 0) {
|
||||
free(buf);
|
||||
croak("unable to read from sharedarea %d", id);
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
ST(0) = sv_newmortal();
|
||||
sv_usepvn(ST(0), buf, rlen);
|
||||
XSRETURN(1);
|
||||
}
|
||||
|
||||
XS(XS_sharedarea_readfast) {
|
||||
dXSARGS;
|
||||
int id;
|
||||
uint64_t pos;
|
||||
uint64_t len = 0;
|
||||
psgi_check_args(3);
|
||||
|
||||
id = SvIV(ST(0));
|
||||
pos = SvIV(ST(1));
|
||||
char *buf = SvPV_nolen(ST(2));
|
||||
|
||||
if (items > 3) {
|
||||
len = SvIV(ST(3));
|
||||
}
|
||||
|
||||
if (uwsgi_sharedarea_read(id, pos, buf, len)) {
|
||||
croak("unable to (fast) read from sharedarea %d", id);
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
XS(XS_sharedarea_write) {
|
||||
dXSARGS;
|
||||
int id;
|
||||
uint64_t pos;
|
||||
STRLEN vallen;
|
||||
|
||||
psgi_check_args(3);
|
||||
|
||||
id = SvIV(ST(0));
|
||||
pos = SvIV(ST(1));
|
||||
char *value = SvPV(ST(2), vallen);
|
||||
|
||||
if (uwsgi_sharedarea_write(id, pos, value, vallen)) {
|
||||
croak("unable to write to sharedarea %d", id);
|
||||
XSRETURN_UNDEF;
|
||||
}
|
||||
|
||||
XSRETURN_YES;
|
||||
}
|
||||
|
||||
|
||||
XS(XS_chunked_read) {
|
||||
dXSARGS;
|
||||
int timeout = 0;
|
||||
@@ -740,6 +904,9 @@ void init_perl_embedded_module() {
|
||||
psgi_xs(websocket_recv);
|
||||
psgi_xs(websocket_recv_nb);
|
||||
psgi_xs(websocket_send);
|
||||
psgi_xs(websocket_send_from_sharedarea);
|
||||
psgi_xs(websocket_send_binary);
|
||||
psgi_xs(websocket_send_binary_from_sharedarea);
|
||||
psgi_xs(postfork);
|
||||
psgi_xs(atexit);
|
||||
|
||||
@@ -757,5 +924,9 @@ void init_perl_embedded_module() {
|
||||
|
||||
psgi_xs(chunked_read);
|
||||
psgi_xs(chunked_read_nb);
|
||||
}
|
||||
|
||||
psgi_xs(sharedarea_read);
|
||||
psgi_xs(sharedarea_readfast);
|
||||
psgi_xs(sharedarea_write);
|
||||
psgi_xs(sharedarea_wait);
|
||||
}
|
||||
|
||||
@@ -833,7 +833,7 @@ void init_uwsgi_embedded_module() {
|
||||
init_uwsgi_module_spooler(new_uwsgi_module);
|
||||
}
|
||||
|
||||
if (uwsgi.sharedareasize > 0 && uwsgi.sharedarea) {
|
||||
if (uwsgi.sharedareas) {
|
||||
init_uwsgi_module_sharedarea(new_uwsgi_module);
|
||||
}
|
||||
|
||||
|
||||
+118
-163
@@ -1066,6 +1066,27 @@ PyObject *py_uwsgi_websocket_send(PyObject * self, PyObject * args) {
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_websocket_send_binary(PyObject * self, PyObject * args) {
|
||||
char *message = NULL;
|
||||
Py_ssize_t message_len = 0;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s#:websocket_send_binary", &message, &message_len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct wsgi_request *wsgi_req = py_current_wsgi_req();
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_websocket_send_binary(wsgi_req, message, message_len);
|
||||
UWSGI_GET_GIL
|
||||
if (ret < 0) {
|
||||
return PyErr_Format(PyExc_IOError, "unable to send websocket binary message");
|
||||
}
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_chunked_read(PyObject * self, PyObject * args) {
|
||||
int timeout = 0;
|
||||
if (!PyArg_ParseTuple(args, "|i:chunked_read", &timeout)) {
|
||||
@@ -1426,222 +1447,149 @@ PyObject *py_uwsgi_extract(PyObject * self, PyObject * args) {
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_inclong(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_sharedarea_inc64(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
uint64_t value = 1;
|
||||
uint64_t current_value = 0;
|
||||
int64_t value = 1;
|
||||
|
||||
if (uwsgi.sharedareasize <= 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l|l:sharedarea_inclong", &pos, &value)) {
|
||||
if (!PyArg_ParseTuple(args, "il|l:sharedarea_inc64", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pos + 8 >= uwsgi.page_size * uwsgi.sharedareasize) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
memcpy(¤t_value, uwsgi.sharedarea + pos, 8);
|
||||
value = current_value + value;
|
||||
memcpy(uwsgi.sharedarea + pos, &value, 8);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
int ret = uwsgi_sharedarea_inc64(id, pos, value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_inc64()");
|
||||
}
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_writelong(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_sharedarea_write64(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
uint64_t value = 0;
|
||||
int64_t value = 0;
|
||||
|
||||
if (uwsgi.sharedareasize <= 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ll:sharedarea_writelong", &pos, &value)) {
|
||||
if (!PyArg_ParseTuple(args, "ill:sharedarea_write64", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pos + 8 >= uwsgi.page_size * uwsgi.sharedareasize) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_write64(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
memcpy(uwsgi.sharedarea + pos, &value, 8);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_write64()");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_write(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
char *value;
|
||||
Py_ssize_t value_len = 0;
|
||||
|
||||
if (uwsgi.sharedareasize <= 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ls#:sharedarea_write", &pos, &value, &value_len)) {
|
||||
if (!PyArg_ParseTuple(args, "ils#:sharedarea_write", &id, &pos, &value, &value_len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pos + value_len >= uwsgi.page_size * uwsgi.sharedareasize) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_write(id, pos, value, value_len);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_write()");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_write8(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int8_t value;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "ilb:sharedarea_write8", &id, &pos, &value)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_write8(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_write8()");
|
||||
}
|
||||
|
||||
memcpy(uwsgi.sharedarea + pos, value, value_len);
|
||||
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value_len);
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_writebyte(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_sharedarea_read64(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
char value;
|
||||
int64_t value;
|
||||
|
||||
if (uwsgi.sharedareasize <= 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
|
||||
if (!PyArg_ParseTuple(args, "lb:sharedarea_writebyte", &pos, &value)) {
|
||||
if (!PyArg_ParseTuple(args, "il:sharedarea_read64", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pos >= uwsgi.page_size * uwsgi.sharedareasize) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_read64(id, pos, &value);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
uwsgi.sharedarea[pos] = value;
|
||||
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_readlong(PyObject * self, PyObject * args) {
|
||||
uint64_t pos = 0;
|
||||
uint64_t value;
|
||||
|
||||
if (uwsgi.sharedareasize <= 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l:sharedarea_readlong", &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pos + 8 >= uwsgi.page_size * uwsgi.sharedareasize) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
memcpy(&value, uwsgi.sharedarea + pos, 8);
|
||||
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read64()");
|
||||
}
|
||||
|
||||
return PyLong_FromLong(value);
|
||||
|
||||
}
|
||||
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_readbyte(PyObject * self, PyObject * args) {
|
||||
PyObject *py_uwsgi_sharedarea_read8(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
int8_t byte;
|
||||
|
||||
if (uwsgi.sharedareasize <= 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l:sharedarea_readbyte", &pos)) {
|
||||
if (!PyArg_ParseTuple(args, "il:sharedarea_read8", &id, &pos)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pos >= uwsgi.page_size * uwsgi.sharedareasize) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int ret = uwsgi_sharedarea_read8(id, pos, &byte);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
|
||||
char value = uwsgi.sharedarea[pos];
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
|
||||
return PyInt_FromLong(value);
|
||||
if (ret) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read8()");
|
||||
}
|
||||
|
||||
return PyInt_FromLong(byte);
|
||||
}
|
||||
|
||||
PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) {
|
||||
int id;
|
||||
uint64_t pos = 0;
|
||||
uint64_t len = 1;
|
||||
uint64_t len = 0;
|
||||
|
||||
if (uwsgi.sharedareasize <= 0) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "l|l:sharedarea_read", &pos, &len)) {
|
||||
if (!PyArg_ParseTuple(args, "il|l:sharedarea_read", &id, &pos, &len)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pos + len >= uwsgi.page_size * uwsgi.sharedareasize) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
if (!len) {
|
||||
struct uwsgi_sharedarea *sa = uwsgi_sharedarea_get_by_id(id, pos);
|
||||
if (!sa) {
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read()");
|
||||
}
|
||||
len = (sa->max_pos+1)-pos;
|
||||
}
|
||||
|
||||
PyObject *ret = PyString_FromStringAndSize(NULL, len);
|
||||
@@ -1652,14 +1600,16 @@ PyObject *py_uwsgi_sharedarea_read(PyObject * self, PyObject * args) {
|
||||
#endif
|
||||
|
||||
UWSGI_RELEASE_GIL
|
||||
int64_t rlen = uwsgi_sharedarea_read(id, pos, storage, len);
|
||||
UWSGI_GET_GIL
|
||||
|
||||
uwsgi_wlock(uwsgi.sa_lock);
|
||||
if (rlen < 0) {
|
||||
Py_DECREF(ret);
|
||||
return PyErr_Format(PyExc_ValueError, "error calling uwsgi_sharedarea_read()");
|
||||
}
|
||||
|
||||
memcpy(storage, uwsgi.sharedarea + pos, len);
|
||||
|
||||
uwsgi_rwunlock(uwsgi.sa_lock);
|
||||
|
||||
UWSGI_GET_GIL
|
||||
// HACK: we are safe as rlen can only be lower or equal to len
|
||||
Py_SIZE(ret) = rlen;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -2519,11 +2469,11 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
{"ready", py_uwsgi_ready, METH_VARARGS, ""},
|
||||
|
||||
{"set_user_harakiri", py_uwsgi_set_user_harakiri, METH_VARARGS, ""},
|
||||
//{"call_hook", py_uwsgi_call_hook, METH_VARARGS, ""},
|
||||
|
||||
{"websocket_recv", py_uwsgi_websocket_recv, METH_VARARGS, ""},
|
||||
{"websocket_recv_nb", py_uwsgi_websocket_recv_nb, METH_VARARGS, ""},
|
||||
{"websocket_send", py_uwsgi_websocket_send, METH_VARARGS, ""},
|
||||
{"websocket_send_binary", py_uwsgi_websocket_send_binary, METH_VARARGS, ""},
|
||||
{"websocket_handshake", py_uwsgi_websocket_handshake, METH_VARARGS, ""},
|
||||
|
||||
{"chunked_read", py_uwsgi_chunked_read, METH_VARARGS, ""},
|
||||
@@ -2538,11 +2488,16 @@ static PyMethodDef uwsgi_advanced_methods[] = {
|
||||
static PyMethodDef uwsgi_sa_methods[] = {
|
||||
{"sharedarea_read", py_uwsgi_sharedarea_read, METH_VARARGS, ""},
|
||||
{"sharedarea_write", py_uwsgi_sharedarea_write, METH_VARARGS, ""},
|
||||
{"sharedarea_readbyte", py_uwsgi_sharedarea_readbyte, METH_VARARGS, ""},
|
||||
{"sharedarea_writebyte", py_uwsgi_sharedarea_writebyte, METH_VARARGS, ""},
|
||||
{"sharedarea_readlong", py_uwsgi_sharedarea_readlong, METH_VARARGS, ""},
|
||||
{"sharedarea_writelong", py_uwsgi_sharedarea_writelong, METH_VARARGS, ""},
|
||||
{"sharedarea_inclong", py_uwsgi_sharedarea_inclong, METH_VARARGS, ""},
|
||||
{"sharedarea_readbyte", py_uwsgi_sharedarea_read8, METH_VARARGS, ""},
|
||||
{"sharedarea_writebyte", py_uwsgi_sharedarea_write8, METH_VARARGS, ""},
|
||||
{"sharedarea_read8", py_uwsgi_sharedarea_read8, METH_VARARGS, ""},
|
||||
{"sharedarea_write8", py_uwsgi_sharedarea_write8, METH_VARARGS, ""},
|
||||
{"sharedarea_readlong", py_uwsgi_sharedarea_read64, METH_VARARGS, ""},
|
||||
{"sharedarea_writelong", py_uwsgi_sharedarea_write64, METH_VARARGS, ""},
|
||||
{"sharedarea_read64", py_uwsgi_sharedarea_read64, METH_VARARGS, ""},
|
||||
{"sharedarea_write64", py_uwsgi_sharedarea_write64, METH_VARARGS, ""},
|
||||
{"sharedarea_inclong", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""},
|
||||
{"sharedarea_inc64", py_uwsgi_sharedarea_inc64, METH_VARARGS, ""},
|
||||
{NULL, NULL},
|
||||
};
|
||||
|
||||
|
||||
@@ -30,6 +30,12 @@
|
||||
#define PYTHREE
|
||||
#endif
|
||||
|
||||
#if (PY_VERSION_HEX < 0x02060000)
|
||||
#ifndef Py_SIZE
|
||||
#define Py_SIZE(ob) (((PyVarObject*)(ob))->ob_size)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define UWSGI_GET_GIL up.gil_get();
|
||||
#define UWSGI_RELEASE_GIL up.gil_release();
|
||||
|
||||
|
||||
@@ -37,6 +37,7 @@ struct uwsgi_rbthreads {
|
||||
int rbthreads;
|
||||
int (*orig_wait_write_hook) (int, int);
|
||||
int (*orig_wait_read_hook) (int, int);
|
||||
int (*orig_wait_milliseconds_hook) (int);
|
||||
} urbts;
|
||||
|
||||
static struct uwsgi_option rbthreads_options[] = {
|
||||
@@ -142,6 +143,20 @@ static int rbthreads_wait_fd_read(int fd, int timeout) {
|
||||
return urbt.ret;
|
||||
}
|
||||
|
||||
static void *rbthreads_wait_milliseconds_do(void *arg) {
|
||||
struct uwsgi_rbthread *urbt = (struct uwsgi_rbthread *) arg;
|
||||
urbt->ret = urbts.orig_wait_milliseconds_hook(urbt->timeout);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int rbthreads_wait_milliseconds(int timeout) {
|
||||
struct uwsgi_rbthread urbt;
|
||||
urbt.timeout = timeout;
|
||||
rb_thread_call_without_gvl(rbthreads_wait_milliseconds_do, &urbt, NULL, NULL);
|
||||
return urbt.ret;
|
||||
}
|
||||
|
||||
|
||||
static void rbthreads_loop() {
|
||||
struct uwsgi_plugin *rup = uwsgi_plugin_get("rack");
|
||||
// disable init_thread warning
|
||||
@@ -152,8 +167,10 @@ static void rbthreads_loop() {
|
||||
// override read/write nb hooks
|
||||
urbts.orig_wait_write_hook = uwsgi.wait_write_hook;
|
||||
urbts.orig_wait_read_hook = uwsgi.wait_read_hook;
|
||||
urbts.orig_wait_milliseconds_hook = uwsgi.wait_milliseconds_hook;
|
||||
uwsgi.wait_write_hook = rbthreads_wait_fd_write;
|
||||
uwsgi.wait_read_hook = rbthreads_wait_fd_read;
|
||||
uwsgi.wait_milliseconds_hook = rbthreads_wait_milliseconds;
|
||||
|
||||
int i;
|
||||
for(i=1;i<uwsgi.threads;i++) {
|
||||
|
||||
@@ -56,6 +56,8 @@ static int uwsgi_routing_func_hash(struct wsgi_request *wsgi_req, struct uwsgi_r
|
||||
// skip last semicolon
|
||||
if (urhc->items[ilen-1] == ';') items--;
|
||||
|
||||
if (items < 1) return UWSGI_ROUTE_BREAK;
|
||||
|
||||
uint32_t hashed_result = h % items;
|
||||
uint32_t found = 0;
|
||||
char *value = urhc->items;
|
||||
|
||||
@@ -112,7 +112,11 @@ static int uwsgi_rpc_xmlrpc(struct wsgi_request *wsgi_req, xmlDoc *doc, char **a
|
||||
xmlChar *xmlbuf;
|
||||
int xlen = 0;
|
||||
xmlDocDumpFormatMemory(rdoc, &xmlbuf, &xlen, 1);
|
||||
uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6);
|
||||
if (uwsgi_response_prepare_headers(wsgi_req,"200 OK", 6)) {
|
||||
xmlFreeDoc(rdoc);
|
||||
xmlFree(xmlbuf);
|
||||
return -1;
|
||||
}
|
||||
uwsgi_response_add_content_length(wsgi_req, xlen);
|
||||
uwsgi_response_add_content_type(wsgi_req, "application/xml", 15);
|
||||
uwsgi_response_write_body_do(wsgi_req, (char *) xmlbuf, xlen);
|
||||
|
||||
@@ -3,9 +3,8 @@
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
struct uwsgi_symcall {
|
||||
char *symcall_function_name;
|
||||
struct uwsgi_string_list *symcall_function_name;
|
||||
int (*symcall_function)(struct wsgi_request *);
|
||||
|
||||
struct uwsgi_string_list *rpc;
|
||||
struct uwsgi_string_list *post_fork;
|
||||
} usym;
|
||||
@@ -13,24 +12,40 @@ struct uwsgi_symcall {
|
||||
struct uwsgi_plugin symcall_plugin;
|
||||
|
||||
static struct uwsgi_option uwsgi_symcall_options[] = {
|
||||
{"symcall", required_argument, 0, "load the specified C symbol as the symcall request handler", uwsgi_opt_set_str, &usym.symcall_function_name, 0},
|
||||
{"symcall", required_argument, 0, "load the specified C symbol as the symcall request handler (supports <mountpoint=func> too)", uwsgi_opt_add_string_list, &usym.symcall_function_name, 0},
|
||||
{"symcall-register-rpc", required_argument, 0, "load the specified C symbol as an RPC function (syntax: name function)", uwsgi_opt_add_string_list, &usym.rpc, 0},
|
||||
{"symcall-post-fork", required_argument, 0, "call the specified C symbol after each fork()", uwsgi_opt_add_string_list, &usym.post_fork, 0},
|
||||
{0, 0, 0, 0},
|
||||
};
|
||||
|
||||
static void uwsgi_symcall_init(){
|
||||
if (usym.symcall_function_name) {
|
||||
usym.symcall_function = dlsym(RTLD_DEFAULT, usym.symcall_function_name);
|
||||
if (!usym.symcall_function) {
|
||||
uwsgi_log("unable to find symbol \"%s\" in process address space\n", usym.symcall_function_name);
|
||||
struct uwsgi_string_list *usl = NULL;
|
||||
int has_mountpoints = 0;
|
||||
uwsgi_foreach(usl, usym.symcall_function_name) {
|
||||
char *func = usl->value, *mountpoint = "";
|
||||
char *equal = strchr(usl->value, '=');
|
||||
if (equal) {
|
||||
*equal = 0;
|
||||
func = equal+1;
|
||||
mountpoint = usl->value;
|
||||
has_mountpoints = 1;
|
||||
}
|
||||
usl->custom_ptr = dlsym(RTLD_DEFAULT, func);
|
||||
if (!usl->custom_ptr) {
|
||||
uwsgi_log("unable to find symbol \"%s\" in process address space\n", func);
|
||||
exit(1);
|
||||
}
|
||||
uwsgi_log("symcall function ptr: %p\n", usym.symcall_function);
|
||||
int id = uwsgi_apps_cnt;
|
||||
struct uwsgi_app *ua = uwsgi_add_app(id, symcall_plugin.modifier1, mountpoint, strlen(mountpoint), usl->custom_ptr, NULL);
|
||||
uwsgi_log("symcall app %d (mountpoint: \"%.*s\") mapped to function ptr: %p\n", id, ua->mountpoint_len, ua->mountpoint, usl->custom_ptr);
|
||||
if (equal) *equal = '=';
|
||||
}
|
||||
|
||||
struct uwsgi_string_list *usl = usym.rpc;
|
||||
while(usl) {
|
||||
if (!has_mountpoints && usym.symcall_function_name) {
|
||||
usym.symcall_function = usym.symcall_function_name->custom_ptr;
|
||||
}
|
||||
|
||||
uwsgi_foreach(usl, usym.rpc) {
|
||||
char *space = strchr(usl->value, ' ');
|
||||
if (!space) {
|
||||
uwsgi_log("invalid symcall RPC syntax, must be: rpcname symbol\n");
|
||||
@@ -55,6 +70,26 @@ static int uwsgi_symcall_request(struct wsgi_request *wsgi_req) {
|
||||
if (usym.symcall_function) {
|
||||
return usym.symcall_function(wsgi_req);
|
||||
}
|
||||
|
||||
if (uwsgi_parse_vars(wsgi_req)) return -1;
|
||||
|
||||
wsgi_req->app_id = uwsgi_get_app_id(wsgi_req, wsgi_req->appid, wsgi_req->appid_len, symcall_plugin.modifier1);
|
||||
if (wsgi_req->app_id == -1 && !uwsgi.no_default_app && uwsgi.default_app > -1) {
|
||||
if (uwsgi_apps[uwsgi.default_app].modifier1 == symcall_plugin.modifier1) {
|
||||
wsgi_req->app_id = uwsgi.default_app;
|
||||
}
|
||||
}
|
||||
|
||||
if (wsgi_req->app_id == -1) {
|
||||
uwsgi_404(wsgi_req);
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
|
||||
if (ua->interpreter) {
|
||||
int (*func)(struct wsgi_request *) = (int (*)(struct wsgi_request *)) ua->interpreter;
|
||||
return func(wsgi_req);
|
||||
}
|
||||
return UWSGI_OK;
|
||||
}
|
||||
|
||||
@@ -82,6 +117,21 @@ static void uwsgi_symcall_post_fork() {
|
||||
}
|
||||
}
|
||||
|
||||
static int uwsgi_symcall_mule(char *opt) {
|
||||
if (uwsgi_endswith(opt, "()")) {
|
||||
char *func_name = uwsgi_concat2n(opt, strlen(opt)-2, "", 0);
|
||||
void (*func)() = dlsym(RTLD_DEFAULT, func_name);
|
||||
if (!func) {
|
||||
uwsgi_log("unable to find symbol \"%s\" in process address space\n", func_name);
|
||||
exit(1);
|
||||
}
|
||||
free(func_name);
|
||||
func();
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct uwsgi_plugin symcall_plugin = {
|
||||
|
||||
.name = "symcall",
|
||||
@@ -92,6 +142,6 @@ struct uwsgi_plugin symcall_plugin = {
|
||||
.after_request = uwsgi_symcall_after_request,
|
||||
.rpc = uwsgi_symcall_rpc,
|
||||
.post_fork = uwsgi_symcall_post_fork,
|
||||
|
||||
.mule = uwsgi_symcall_mule,
|
||||
};
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ static int transform_offload(struct wsgi_request *wsgi_req, struct uwsgi_transfo
|
||||
if (ut->ub) {
|
||||
ssize_t wlen = write(ut->fd, ut->ub->buf, ut->ub->pos);
|
||||
if (wlen != (ssize_t) ut->ub->pos) {
|
||||
uwsgi_error("transform_offload/write()");
|
||||
uwsgi_req_error("transform_offload/write()");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -76,7 +76,7 @@ static int transform_offload(struct wsgi_request *wsgi_req, struct uwsgi_transfo
|
||||
if (ut->fd > -1) {
|
||||
ssize_t wlen = write(ut->fd, ut->chunk->buf, ut->chunk->pos);
|
||||
if (wlen != (ssize_t) ut->chunk->pos) {
|
||||
uwsgi_error("transform_offload/write()");
|
||||
uwsgi_req_error("transform_offload/write()");
|
||||
return -1;
|
||||
}
|
||||
ut->len += wlen;
|
||||
|
||||
@@ -43,7 +43,7 @@ static int transform_tofile(struct wsgi_request *wsgi_req, struct uwsgi_transfor
|
||||
while(remains) {
|
||||
ssize_t rlen = write(fd, ub->buf + (ub->pos - remains), remains);
|
||||
if (rlen <= 0) {
|
||||
uwsgi_error("transform_tofile()/write()");
|
||||
uwsgi_req_error("transform_tofile()/write()");
|
||||
unlink(uttc->filename->buf);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -285,7 +285,7 @@ extern "C" uint64_t uwsgi_v8_rpc(void * func, uint8_t argc, char **argv, uint16_
|
||||
if (!*robj) {
|
||||
return 0;
|
||||
}
|
||||
uint16_t rlen = robj->Length();
|
||||
uint64_t rlen = (uint64_t) robj->Length();
|
||||
if (rlen > 0) {
|
||||
*buffer = (char *)uwsgi_malloc(rlen);
|
||||
memcpy(*buffer, *r_value, rlen);
|
||||
|
||||
@@ -208,6 +208,59 @@ int uwsgi_proto_base_write(struct wsgi_request * wsgi_req, char *buf, size_t len
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE: len is a pointer as it could be changed on the fly
|
||||
*/
|
||||
int uwsgi_proto_base_writev(struct wsgi_request * wsgi_req, struct iovec *iov, size_t *len) {
|
||||
size_t i,needed = 0;
|
||||
// count the number of bytes to write
|
||||
for(i=0;i<*len;i++) needed += iov[i].iov_len;
|
||||
ssize_t wlen = writev(wsgi_req->fd, iov, *len);
|
||||
if (wlen > 0) {
|
||||
wsgi_req->write_pos += wlen;
|
||||
if ((size_t)wlen == needed) {
|
||||
return UWSGI_OK;
|
||||
}
|
||||
// now the complex part, we need to rebuild iovec and len...
|
||||
size_t orig_len = *len;
|
||||
size_t new_len = orig_len;
|
||||
// first remove the consumed items
|
||||
size_t first_iov = 0;
|
||||
size_t skip_bytes = 0;
|
||||
for(i=0;i<orig_len;i++) {
|
||||
if (iov[i].iov_len <= (size_t)wlen) {
|
||||
wlen -= iov[i].iov_len;
|
||||
new_len--;
|
||||
}
|
||||
else {
|
||||
first_iov = i;
|
||||
skip_bytes = wlen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
*len = new_len;
|
||||
// now moves remaining iovec's to top
|
||||
size_t pos = 0;
|
||||
for(i=first_iov;i<orig_len;i++) {
|
||||
if (pos == 0) {
|
||||
iov[i].iov_base += skip_bytes;
|
||||
iov[i].iov_len -= skip_bytes;
|
||||
}
|
||||
iov[pos].iov_base = iov[i].iov_base;
|
||||
iov[pos].iov_len = iov[i].iov_len;
|
||||
pos++;
|
||||
}
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
if (wlen < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINPROGRESS) {
|
||||
return UWSGI_AGAIN;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
int uwsgi_proto_ssl_write(struct wsgi_request * wsgi_req, char *buf, size_t len) {
|
||||
int ret = -1;
|
||||
|
||||
@@ -565,6 +565,7 @@ void uwsgi_proto_http_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_base_writev;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
|
||||
@@ -98,6 +98,7 @@ void uwsgi_proto_puwsgi_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_noop_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_base_writev;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_puwsgi_close;
|
||||
|
||||
@@ -115,6 +115,7 @@ void uwsgi_proto_scgi_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_base_writev;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
@@ -128,6 +129,7 @@ void uwsgi_proto_scgi_nph_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_base_writev;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
|
||||
@@ -219,6 +219,7 @@ void uwsgi_proto_uwsgi_setup(struct uwsgi_socket *uwsgi_sock) {
|
||||
uwsgi_sock->proto_fix_headers = uwsgi_proto_base_fix_headers;
|
||||
uwsgi_sock->proto_read_body = uwsgi_proto_base_read_body;
|
||||
uwsgi_sock->proto_write = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_writev = uwsgi_proto_base_writev;
|
||||
uwsgi_sock->proto_write_headers = uwsgi_proto_base_write;
|
||||
uwsgi_sock->proto_sendfile = uwsgi_proto_base_sendfile;
|
||||
uwsgi_sock->proto_close = uwsgi_proto_base_close;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
my $app = sub {
|
||||
my $env = shift;
|
||||
$env->{'psgi.input'}->read(my $body, $env->{CONTENT_LENGTH});
|
||||
return [200, ['Content-Type' => 'x-application/binary'], [$body]];
|
||||
};
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
#uwsgi --http-socket :9090 --psgi t/core/apps/read_body_and_send.pl
|
||||
|
||||
use IO::Socket::INET;
|
||||
|
||||
my @chars = ("A".."Z", "a".."z");
|
||||
|
||||
foreach(0..100) {
|
||||
$size = int(rand(8*1024*1024));
|
||||
print "testing: round ".$_." body size ".$size."\n";
|
||||
my $req = "POST /foobar HTTP/1.0\r\n";
|
||||
$req .= 'Content-Length: '.$size."\r\n\r\n";
|
||||
my $body = '';
|
||||
$body .= $chars[rand @chars] for 1..($size);
|
||||
$req .= $body;
|
||||
|
||||
my $s = IO::Socket::INET->new(PeerAddr => $ARGV[0]);
|
||||
$s->send($req);
|
||||
|
||||
my $response = '';
|
||||
while(1) {
|
||||
$s->recv(my $buf, 4096);
|
||||
last unless length($buf);
|
||||
$response .= $buf;
|
||||
}
|
||||
$s->close;
|
||||
|
||||
if ($response ne "HTTP/1.0 200 OK\r\nContent-Type: x-application/binary\r\n\r\n".$body) {
|
||||
print "TEST FOR ROUND ".$_." FAILED\n";
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
print "test result: SUCCESS\n";
|
||||
+2
-1
@@ -2,7 +2,7 @@ Gem::Specification.new do |s|
|
||||
s.name = 'uwsgi'
|
||||
s.license = 'GPL-2'
|
||||
s.version = `python -c "import uwsgiconfig as uc; print uc.uwsgi_version"`.sub(/-dev-.*/,'')
|
||||
s.date = '2013-11-09'
|
||||
s.date = '2013-11-17'
|
||||
s.summary = "uWSGI"
|
||||
s.description = "The uWSGI server for Ruby/Rack"
|
||||
s.authors = ["Unbit"]
|
||||
@@ -12,4 +12,5 @@ Gem::Specification.new do |s|
|
||||
s.require_paths = ['.']
|
||||
s.executables << 'uwsgi'
|
||||
s.homepage = 'http://projects.unbit.it/uwsgi'
|
||||
s.add_runtime_dependency 'rack'
|
||||
end
|
||||
|
||||
@@ -337,10 +337,6 @@ extern int pivot_root(const char *new_root, const char *put_old);
|
||||
#undef __EXTENSIONS__
|
||||
#endif
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
#include <zmq.h>
|
||||
#endif
|
||||
|
||||
#define UWSGI_CACHE_FLAG_UNGETTABLE 0x01
|
||||
#define UWSGI_CACHE_FLAG_UPDATE 1 << 1
|
||||
#define UWSGI_CACHE_FLAG_LOCAL 1 << 2
|
||||
@@ -448,13 +444,14 @@ struct uwsgi_dyn_dict {
|
||||
uint64_t hits;
|
||||
int status;
|
||||
|
||||
struct uwsgi_dyn_dict *prev;
|
||||
struct uwsgi_dyn_dict *next;
|
||||
|
||||
#ifdef UWSGI_PCRE
|
||||
pcre *pattern;
|
||||
pcre_extra *pattern_extra;
|
||||
#endif
|
||||
|
||||
struct uwsgi_dyn_dict *prev;
|
||||
struct uwsgi_dyn_dict *next;
|
||||
};
|
||||
|
||||
struct uwsgi_hook {
|
||||
@@ -583,12 +580,13 @@ struct uwsgi_daemon {
|
||||
// frequency of pidfile checks (default 10 secs)
|
||||
int freq;
|
||||
|
||||
int control;
|
||||
struct uwsgi_daemon *next;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
char *legion;
|
||||
#endif
|
||||
|
||||
int control;
|
||||
struct uwsgi_daemon *next;
|
||||
};
|
||||
|
||||
struct uwsgi_logger {
|
||||
@@ -713,6 +711,19 @@ struct uwsgi_hash_algo *uwsgi_hash_algo_get(char *);
|
||||
void uwsgi_hash_algo_register(char *, uint32_t(*)(char *, uint64_t));
|
||||
void uwsgi_hash_algo_register_all(void);
|
||||
|
||||
struct uwsgi_sharedarea {
|
||||
int id;
|
||||
int pages;
|
||||
int fd;
|
||||
struct uwsgi_lock_item *lock;
|
||||
char *area;
|
||||
uint64_t max_pos;
|
||||
uint64_t updates;
|
||||
uint64_t hits;
|
||||
uint8_t honour_used;
|
||||
uint64_t used;
|
||||
};
|
||||
|
||||
// maintain alignment here !!!
|
||||
struct uwsgi_cache_item {
|
||||
// item specific flags
|
||||
@@ -848,6 +859,7 @@ struct uwsgi_opt {
|
||||
#define UWSGI_OPTION_MULE_HARAKIRI 18
|
||||
#define UWSGI_OPTION_MAX_WORKER_LIFETIME 19
|
||||
#define UWSGI_OPTION_MIN_WORKER_LIFETIME 20
|
||||
#define UWSGI_OPTION_LOG_IOERROR 21
|
||||
|
||||
#define UWSGI_SPOOLER_EXTERNAL 1
|
||||
|
||||
@@ -928,6 +940,8 @@ struct uwsgi_socket {
|
||||
void (*proto_close) (struct wsgi_request *);
|
||||
// special hook to call (if needed) in multithread mode
|
||||
void (*proto_thread_fixup) (struct uwsgi_socket *, int);
|
||||
// optimization for vectors
|
||||
int (*proto_writev) (struct wsgi_request *, struct iovec *, size_t *);
|
||||
|
||||
int edge_trigger;
|
||||
int *retry;
|
||||
@@ -937,11 +951,8 @@ struct uwsgi_socket {
|
||||
// this is a special map for having socket->thread mapping
|
||||
int *fd_threads;
|
||||
|
||||
#ifdef UWSGI_UUID
|
||||
// generally used by zeromq handlers
|
||||
char uuid[37];
|
||||
#endif
|
||||
|
||||
// currently used by zeromq handlers
|
||||
void *pub;
|
||||
void *pull;
|
||||
pthread_key_t key;
|
||||
@@ -958,12 +969,13 @@ struct uwsgi_socket {
|
||||
int shared;
|
||||
int from_shared;
|
||||
|
||||
// used for avoiding vacuum mess
|
||||
ino_t inode;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
SSL_CTX *ssl_ctx;
|
||||
#endif
|
||||
|
||||
// used for avoiding vacuum mess
|
||||
ino_t inode;
|
||||
};
|
||||
|
||||
struct uwsgi_protocol {
|
||||
@@ -1440,6 +1452,7 @@ struct wsgi_request {
|
||||
|
||||
int suspended;
|
||||
uint64_t write_errors;
|
||||
uint64_t read_errors;
|
||||
|
||||
int *ovector;
|
||||
size_t post_cl;
|
||||
@@ -1486,6 +1499,7 @@ struct wsgi_request {
|
||||
struct uwsgi_string_list *remove_headers;
|
||||
|
||||
struct uwsgi_buffer *websocket_buf;
|
||||
struct uwsgi_buffer *websocket_send_buf;
|
||||
size_t websocket_need;
|
||||
int websocket_phase;
|
||||
uint8_t websocket_opcode;
|
||||
@@ -1534,15 +1548,6 @@ struct wsgi_request {
|
||||
#ifdef UWSGI_SSL
|
||||
SSL *ssl;
|
||||
#endif
|
||||
|
||||
struct msghdr msg;
|
||||
union {
|
||||
struct cmsghdr cmsg;
|
||||
// should be enough...
|
||||
char control[64];
|
||||
} msg_control;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -2003,9 +2008,14 @@ struct uwsgi_server {
|
||||
struct uwsgi_string_list *hook_as_user_atexit;
|
||||
struct uwsgi_string_list *hook_pre_app;
|
||||
struct uwsgi_string_list *hook_post_app;
|
||||
struct uwsgi_string_list *hook_accepting;
|
||||
struct uwsgi_string_list *hook_accepting1;
|
||||
struct uwsgi_string_list *hook_accepting_once;
|
||||
struct uwsgi_string_list *hook_accepting1_once;
|
||||
|
||||
struct uwsgi_string_list *hook_as_vassal;
|
||||
struct uwsgi_string_list *hook_as_emperor;
|
||||
struct uwsgi_string_list *hook_as_mule;
|
||||
|
||||
|
||||
struct uwsgi_string_list *exec_asap;
|
||||
@@ -2058,6 +2068,8 @@ struct uwsgi_server {
|
||||
struct uwsgi_string_list *umount_as_vassal;
|
||||
struct uwsgi_string_list *umount_as_emperor;
|
||||
|
||||
struct uwsgi_string_list *after_request_hooks;
|
||||
|
||||
struct uwsgi_string_list *wait_for_interface;
|
||||
int wait_for_interface_timeout;
|
||||
|
||||
@@ -2310,8 +2322,9 @@ struct uwsgi_server {
|
||||
int vec_size;
|
||||
|
||||
// shared area
|
||||
char *sharedarea;
|
||||
uint64_t sharedareasize;
|
||||
struct uwsgi_string_list *sharedareas_list;
|
||||
int sharedareas_cnt;
|
||||
struct uwsgi_sharedarea **sharedareas;
|
||||
|
||||
// avoid thundering herd in threaded modes
|
||||
pthread_mutex_t thunder_mutex;
|
||||
@@ -2367,6 +2380,10 @@ struct uwsgi_server {
|
||||
struct uwsgi_route_var *route_vars;
|
||||
#endif
|
||||
|
||||
struct uwsgi_string_list *error_page_403;
|
||||
struct uwsgi_string_list *error_page_404;
|
||||
struct uwsgi_string_list *error_page_500;
|
||||
|
||||
int single_interpreter;
|
||||
|
||||
struct uwsgi_shared *shared;
|
||||
@@ -2410,10 +2427,6 @@ struct uwsgi_server {
|
||||
int signal_socket;
|
||||
int my_signal_socket;
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
int zeromq;
|
||||
void *zmq_context;
|
||||
#endif
|
||||
struct uwsgi_protocol *protocols;
|
||||
struct uwsgi_socket *sockets;
|
||||
struct uwsgi_socket *shared_sockets;
|
||||
@@ -2526,6 +2539,7 @@ struct uwsgi_server {
|
||||
struct uwsgi_rpc *rpc_table;
|
||||
|
||||
// subscription client
|
||||
int subscriptions_blocked;
|
||||
int subscribe_freq;
|
||||
int subscription_tolerance;
|
||||
int unsubscribe_on_graceful_reload;
|
||||
@@ -2593,6 +2607,8 @@ struct uwsgi_server {
|
||||
|
||||
int (*wait_write_hook) (int, int);
|
||||
int (*wait_read_hook) (int, int);
|
||||
int (*wait_milliseconds_hook) (int);
|
||||
int (*wait_read2_hook) (int, int, int, int *);
|
||||
|
||||
struct uwsgi_string_list *schemes;
|
||||
|
||||
@@ -2644,9 +2660,6 @@ struct uwsgi_cron {
|
||||
uint8_t sig;
|
||||
|
||||
char *command;
|
||||
#ifdef UWSGI_SSL
|
||||
char *legion;
|
||||
#endif
|
||||
void (*func)(struct uwsgi_cron *, time_t);
|
||||
|
||||
time_t started_at;
|
||||
@@ -2660,6 +2673,10 @@ struct uwsgi_cron {
|
||||
pid_t pid;
|
||||
|
||||
struct uwsgi_cron *next;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
char *legion;
|
||||
#endif
|
||||
};
|
||||
|
||||
struct uwsgi_shared {
|
||||
@@ -2733,6 +2750,7 @@ struct uwsgi_core {
|
||||
uint64_t offloaded_requests;
|
||||
|
||||
uint64_t write_errors;
|
||||
uint64_t read_errors;
|
||||
uint64_t exceptions;
|
||||
|
||||
pthread_t thread_id;
|
||||
@@ -2802,6 +2820,8 @@ struct uwsgi_worker {
|
||||
|
||||
struct uwsgi_core *cores;
|
||||
|
||||
int accepting;
|
||||
|
||||
char name[0xff];
|
||||
};
|
||||
|
||||
@@ -3201,16 +3221,9 @@ int uwsgi_str4_num(char *);
|
||||
|
||||
#ifdef __linux__
|
||||
#if !defined(__ia64__)
|
||||
void linux_namespace_start(void *);
|
||||
void linux_namespace_jail(void);
|
||||
void linux_namespace_start(void *);
|
||||
void linux_namespace_jail(void);
|
||||
#endif
|
||||
int uwsgi_netlink_veth(char *, char *);
|
||||
int uwsgi_netlink_veth_attach(char *, pid_t);
|
||||
int uwsgi_netlink_ifup(char *);
|
||||
int uwsgi_netlink_ip(char *, char *, int);
|
||||
int uwsgi_netlink_gw(char *, char *);
|
||||
int uwsgi_netlink_rt(char *, char *, int, char *);
|
||||
int uwsgi_netlink_del(char *);
|
||||
#endif
|
||||
|
||||
|
||||
@@ -3229,6 +3242,7 @@ size_t uwsgi_str_num(char *, int);
|
||||
size_t uwsgi_str_occurence(char *, size_t, char);
|
||||
|
||||
int uwsgi_proto_base_write(struct wsgi_request *, char *, size_t);
|
||||
int uwsgi_proto_base_writev(struct wsgi_request *, struct iovec *, size_t *);
|
||||
#ifdef UWSGI_SSL
|
||||
int uwsgi_proto_ssl_write(struct wsgi_request *, char *, size_t);
|
||||
#endif
|
||||
@@ -3249,13 +3263,6 @@ void uwsgi_proto_ssl_close(struct wsgi_request *);
|
||||
uint16_t proto_base_add_uwsgi_header(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
uint16_t proto_base_add_uwsgi_var(struct wsgi_request *, char *, uint16_t, char *, uint16_t);
|
||||
|
||||
#ifdef UWSGI_ZEROMQ
|
||||
void uwsgi_proto_zeromq_setup(struct uwsgi_socket *);
|
||||
ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *, char *, size_t len);
|
||||
void *uwsgi_zeromq_init(void);
|
||||
void uwsgi_zeromq_init_sockets(void);
|
||||
#endif
|
||||
|
||||
// protocols
|
||||
void uwsgi_proto_uwsgi_setup(struct uwsgi_socket *);
|
||||
void uwsgi_proto_puwsgi_setup(struct uwsgi_socket *);
|
||||
@@ -3443,16 +3450,16 @@ struct uwsgi_subscribe_slot {
|
||||
|
||||
uint64_t hits;
|
||||
|
||||
struct uwsgi_subscribe_node *nodes;
|
||||
|
||||
struct uwsgi_subscribe_slot *prev;
|
||||
struct uwsgi_subscribe_slot *next;
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
EVP_PKEY *sign_public_key;
|
||||
EVP_MD_CTX *sign_ctx;
|
||||
#endif
|
||||
|
||||
|
||||
struct uwsgi_subscribe_node *nodes;
|
||||
|
||||
struct uwsgi_subscribe_slot *prev;
|
||||
struct uwsgi_subscribe_slot *next;
|
||||
};
|
||||
|
||||
void mule_send_msg(int, char *, size_t);
|
||||
@@ -3792,11 +3799,14 @@ char *uwsgi_substitute(char *, char *, char *);
|
||||
|
||||
void uwsgi_opt_add_custom_option(char *, char *, void *);
|
||||
void uwsgi_opt_cflags(char *, char *, void *);
|
||||
void uwsgi_opt_build_plugin(char *, char *, void *);
|
||||
void uwsgi_opt_dot_h(char *, char *, void *);
|
||||
void uwsgi_opt_config_py(char *, char *, void *);
|
||||
void uwsgi_opt_connect_and_read(char *, char *, void *);
|
||||
void uwsgi_opt_extract(char *, char *, void *);
|
||||
|
||||
char *uwsgi_get_dot_h();
|
||||
char *uwsgi_get_config_py();
|
||||
char *uwsgi_get_cflags();
|
||||
|
||||
struct uwsgi_string_list *uwsgi_string_list_has_item(struct uwsgi_string_list *, char *, size_t);
|
||||
@@ -3807,6 +3817,7 @@ void uwsgi_setup_systemd();
|
||||
void uwsgi_setup_upstart();
|
||||
void uwsgi_setup_zerg();
|
||||
void uwsgi_setup_inherited_sockets();
|
||||
void uwsgi_setup_emperor();
|
||||
|
||||
#ifdef UWSGI_SSL
|
||||
void uwsgi_ssl_init(void);
|
||||
@@ -3877,6 +3888,8 @@ struct uwsgi_instance {
|
||||
time_t born;
|
||||
time_t last_mod;
|
||||
time_t last_loyal;
|
||||
time_t last_accepting;
|
||||
time_t last_ready;
|
||||
|
||||
time_t last_run;
|
||||
time_t first_run;
|
||||
@@ -3896,6 +3909,9 @@ struct uwsgi_instance {
|
||||
|
||||
int zerg;
|
||||
|
||||
int ready;
|
||||
int accepting;
|
||||
|
||||
struct uwsgi_emperor_scanner *scanner;
|
||||
|
||||
uid_t uid;
|
||||
@@ -4161,6 +4177,7 @@ void uwsgi_subscribe_all(uint8_t, int);
|
||||
|
||||
void uwsgi_websockets_init(void);
|
||||
int uwsgi_websocket_send(struct wsgi_request *, char *, size_t);
|
||||
int uwsgi_websocket_send_binary(struct wsgi_request *, char *, size_t);
|
||||
struct uwsgi_buffer *uwsgi_websocket_recv(struct wsgi_request *);
|
||||
struct uwsgi_buffer *uwsgi_websocket_recv_nb(struct wsgi_request *);
|
||||
|
||||
@@ -4184,6 +4201,8 @@ struct uwsgi_buffer *uwsgi_proto_base_add_header(struct wsgi_request *, char *,
|
||||
|
||||
int uwsgi_simple_wait_write_hook(int, int);
|
||||
int uwsgi_simple_wait_read_hook(int, int);
|
||||
int uwsgi_simple_wait_read2_hook(int, int, int, int *);
|
||||
int uwsgi_simple_wait_milliseconds_hook(int);
|
||||
int uwsgi_response_write_headers_do(struct wsgi_request *);
|
||||
char *uwsgi_request_body_read(struct wsgi_request *, ssize_t , ssize_t *);
|
||||
char *uwsgi_request_body_readline(struct wsgi_request *, ssize_t, ssize_t *);
|
||||
@@ -4192,6 +4211,7 @@ void uwsgi_request_body_seek(struct wsgi_request *, off_t);
|
||||
struct uwsgi_buffer *uwsgi_proto_base_prepare_headers(struct wsgi_request *, char *, uint16_t);
|
||||
struct uwsgi_buffer *uwsgi_proto_base_cgi_prepare_headers(struct wsgi_request *, char *, uint16_t);
|
||||
int uwsgi_response_write_body_do(struct wsgi_request *, char *, size_t);
|
||||
int uwsgi_response_writev_body_do(struct wsgi_request *, struct iovec *, size_t);
|
||||
|
||||
int uwsgi_proto_base_sendfile(struct wsgi_request *, int, size_t, size_t);
|
||||
#ifdef UWSGI_SSL
|
||||
@@ -4553,6 +4573,40 @@ struct uwsgi_protocol *uwsgi_register_protocol(char *, void (*)(struct uwsgi_soc
|
||||
|
||||
void uwsgi_protocols_register(void);
|
||||
|
||||
void uwsgi_build_plugin(char *dir);
|
||||
|
||||
void uwsgi_sharedareas_init();
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init(int);
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_init_ptr(char *, uint64_t);
|
||||
|
||||
int64_t uwsgi_sharedarea_read(int, uint64_t, char *, uint64_t);
|
||||
int uwsgi_sharedarea_write(int, uint64_t, char *, uint64_t);
|
||||
int uwsgi_sharedarea_read64(int, uint64_t, int64_t *);
|
||||
int uwsgi_sharedarea_write64(int, uint64_t, int64_t *);
|
||||
int uwsgi_sharedarea_read8(int, uint64_t, int8_t *);
|
||||
int uwsgi_sharedarea_write8(int, uint64_t, int8_t *);
|
||||
int uwsgi_sharedarea_read16(int, uint64_t, int16_t *);
|
||||
int uwsgi_sharedarea_write16(int, uint64_t, int16_t *);
|
||||
int uwsgi_sharedarea_read32(int, uint64_t, int32_t *);
|
||||
int uwsgi_sharedarea_write32(int, uint64_t, int32_t *);
|
||||
int uwsgi_sharedarea_inc8(int, uint64_t, int8_t);
|
||||
int uwsgi_sharedarea_inc16(int, uint64_t, int16_t);
|
||||
int uwsgi_sharedarea_inc32(int, uint64_t, int32_t);
|
||||
int uwsgi_sharedarea_inc64(int, uint64_t, int64_t);
|
||||
int uwsgi_sharedarea_dec8(int, uint64_t, int8_t);
|
||||
int uwsgi_sharedarea_dec16(int, uint64_t, int16_t);
|
||||
int uwsgi_sharedarea_dec32(int, uint64_t, int32_t);
|
||||
int uwsgi_sharedarea_dec64(int, uint64_t, int64_t);
|
||||
int uwsgi_sharedarea_wait(int, int, int);
|
||||
|
||||
struct uwsgi_sharedarea *uwsgi_sharedarea_get_by_id(int, uint64_t);
|
||||
int uwsgi_websocket_send_from_sharedarea(struct wsgi_request *, int, uint64_t, uint64_t);
|
||||
int uwsgi_websocket_send_binary_from_sharedarea(struct wsgi_request *, int, uint64_t, uint64_t);
|
||||
|
||||
void uwsgi_setup(int, char **, char **);
|
||||
int uwsgi_run(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+78
-36
@@ -1,6 +1,6 @@
|
||||
# uWSGI build system
|
||||
|
||||
uwsgi_version = '1.9.20'
|
||||
uwsgi_version = '1.9.21'
|
||||
|
||||
import os
|
||||
import re
|
||||
@@ -55,6 +55,8 @@ if CPUCOUNT < 1:
|
||||
|
||||
binary_list = []
|
||||
|
||||
started_at = time.time()
|
||||
|
||||
# this is used for reporting (at the end of the build)
|
||||
# the server configuration
|
||||
report = {
|
||||
@@ -71,7 +73,6 @@ report = {
|
||||
'yaml': False,
|
||||
'json': False,
|
||||
'ssl': False,
|
||||
'zeromq': False,
|
||||
'xml': False,
|
||||
'debug': False,
|
||||
'plugin_dir': False,
|
||||
@@ -306,6 +307,24 @@ def build_uwsgi(uc, print_only=False, gcll=None):
|
||||
uwsgi_dot_h = uwsgi_dot_h_content.encode('hex')
|
||||
open('core/dot_h.c', 'w').write('char *uwsgi_dot_h = "%s";\n' % uwsgi_dot_h);
|
||||
gcc_list.append('core/dot_h')
|
||||
|
||||
# embed uwsgiconfig.py in the server binary. It increases the binary size, but will be very useful
|
||||
# if possibile, the blob is compressed
|
||||
if sys.version_info[0] >= 3:
|
||||
uwsgi_config_py_content = open('uwsgiconfig.py', 'rb').read()
|
||||
else:
|
||||
uwsgi_config_py_content = open('uwsgiconfig.py').read()
|
||||
if report['zlib']:
|
||||
import zlib
|
||||
# maximum level of compression
|
||||
uwsgi_config_py_content = zlib.compress(uwsgi_config_py_content, 9)
|
||||
if sys.version_info[0] >= 3:
|
||||
import binascii
|
||||
uwsgi_config_py = binascii.b2a_hex(uwsgi_config_py_content).decode('ascii')
|
||||
else:
|
||||
uwsgi_config_py = uwsgi_config_py_content.encode('hex')
|
||||
open('core/config_py.c', 'w').write('char *uwsgi_config_py = "%s";\n' % uwsgi_config_py);
|
||||
gcc_list.append('core/config_py')
|
||||
|
||||
cflags.append('-DUWSGI_CFLAGS=\\"%s\\"' % uwsgi_cflags)
|
||||
cflags.append('-DUWSGI_BUILD_DATE="\\"%s\\""' % time.strftime("%d %B %Y %H:%M:%S"))
|
||||
@@ -360,7 +379,10 @@ def build_uwsgi(uc, print_only=False, gcll=None):
|
||||
f.close()
|
||||
|
||||
p_cflags = cflags[:]
|
||||
p_cflags += up['CFLAGS']
|
||||
try:
|
||||
p_cflags += up['CFLAGS']
|
||||
except:
|
||||
pass
|
||||
|
||||
if uwsgi_os.startswith('CYGWIN'):
|
||||
try:
|
||||
@@ -431,7 +453,13 @@ def build_uwsgi(uc, print_only=False, gcll=None):
|
||||
except:
|
||||
pass
|
||||
|
||||
libs += up['LIBS']
|
||||
try:
|
||||
libs += up['LIBS']
|
||||
except:
|
||||
pass
|
||||
|
||||
if not 'LDFLAGS' in up:
|
||||
up['LDFLAGS'] = []
|
||||
|
||||
if uwsgi_os == 'Darwin':
|
||||
found_arch = False
|
||||
@@ -495,6 +523,8 @@ def build_uwsgi(uc, print_only=False, gcll=None):
|
||||
print("")
|
||||
print("############## end of uWSGI configuration #############")
|
||||
|
||||
print("total build time: %d seconds" % (time.time() - started_at))
|
||||
|
||||
if bin_name.find("/") < 0:
|
||||
bin_name = './' + bin_name
|
||||
if uc.get('as_shared_library'):
|
||||
@@ -547,7 +577,7 @@ class uConf(object):
|
||||
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron', 'core/hooks',
|
||||
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/chunked',
|
||||
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini', 'core/fsmon', 'core/mount',
|
||||
'core/metrics',
|
||||
'core/metrics', 'core/plugins_builder', 'core/sharedarea',
|
||||
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/transformations', 'core/uwsgi']
|
||||
# add protocols
|
||||
self.gcc_list.append('proto/base')
|
||||
@@ -1127,20 +1157,6 @@ class uConf(object):
|
||||
self.gcc_list.append('core/legion')
|
||||
report['ssl'] = True
|
||||
|
||||
|
||||
if has_uuid and self.get('zeromq'):
|
||||
if self.get('zeromq') == 'auto':
|
||||
if self.has_include('zmq.h'):
|
||||
self.cflags.append("-DUWSGI_ZEROMQ")
|
||||
self.gcc_list.append('proto/zeromq')
|
||||
self.libs.append('-lzmq')
|
||||
report['zeromq'] = True
|
||||
else:
|
||||
self.cflags.append("-DUWSGI_ZEROMQ")
|
||||
self.gcc_list.append('proto/zeromq')
|
||||
self.libs.append('-lzmq')
|
||||
report['zeromq'] = True
|
||||
|
||||
if self.get('xml'):
|
||||
if self.get('xml') == 'auto':
|
||||
xmlconf = spcall('xml2-config --libs')
|
||||
@@ -1195,26 +1211,47 @@ class uConf(object):
|
||||
def build_plugin(path, uc, cflags, ldflags, libs, name = None):
|
||||
path = path.rstrip('/')
|
||||
|
||||
if not os.path.isdir(path):
|
||||
print("Error: unable to find directory '%s'" % path)
|
||||
sys.exit(1)
|
||||
plugin_started_at = time.time()
|
||||
|
||||
up = {}
|
||||
try:
|
||||
execfile('%s/uwsgiplugin.py' % path, up)
|
||||
except:
|
||||
f = open('%s/uwsgiplugin.py' % path)
|
||||
exec(f.read(), up)
|
||||
f.close()
|
||||
|
||||
if os.path.isfile(path):
|
||||
bname = os.path.basename(path)
|
||||
# override path
|
||||
path = os.path.dirname(path)
|
||||
up['GCC_LIST'] = [bname]
|
||||
up['NAME'] = bname.split('.')[0]
|
||||
if not path: path = '.'
|
||||
elif os.path.isdir(path):
|
||||
try:
|
||||
execfile('%s/uwsgiplugin.py' % path, up)
|
||||
except:
|
||||
f = open('%s/uwsgiplugin.py' % path)
|
||||
exec(f.read(), up)
|
||||
f.close()
|
||||
else:
|
||||
print("Error: unable to find directory '%s'" % path)
|
||||
sys.exit(1)
|
||||
|
||||
requires = []
|
||||
|
||||
p_cflags = cflags[:]
|
||||
p_ldflags = ldflags[:]
|
||||
|
||||
p_cflags += up['CFLAGS']
|
||||
p_ldflags += up['LDFLAGS']
|
||||
p_libs = up['LIBS']
|
||||
try:
|
||||
p_cflags += up['CFLAGS']
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
p_ldflags += up['LDFLAGS']
|
||||
except:
|
||||
pass
|
||||
|
||||
try:
|
||||
p_libs = up['LIBS']
|
||||
except:
|
||||
p_libs = []
|
||||
|
||||
post_build = None
|
||||
|
||||
@@ -1355,6 +1392,7 @@ def build_plugin(path, uc, cflags, ldflags, libs, name = None):
|
||||
if post_build:
|
||||
post_build(uc)
|
||||
|
||||
print("build time: %d seconds" % (time.time() - plugin_started_at))
|
||||
print("*** %s plugin built and available in %s ***" % (name, plugin_dest + '.so'))
|
||||
|
||||
def vararg_callback(option, opt_str, value, parser):
|
||||
@@ -1378,7 +1416,7 @@ if __name__ == "__main__":
|
||||
parser.add_option("-f", "--cflags", action="callback", callback=vararg_callback, dest="cflags", help="same as --build but less verbose", metavar="PROFILE")
|
||||
parser.add_option("-u", "--unbit", action="store_true", dest="unbit", help="build unbit profile")
|
||||
parser.add_option("-p", "--plugin", action="callback", callback=vararg_callback, dest="plugin", help="build a plugin as shared library, optionally takes a build profile name", metavar="PLUGIN [PROFILE]")
|
||||
parser.add_option("-x", "--extra-plugin", action="callback", callback=vararg_callback, dest="extra_plugin", help="build an external plugin as shared library, takes an optional include dir", metavar="PLUGIN [INCLUDE_DIR]")
|
||||
parser.add_option("-x", "--extra-plugin", action="callback", callback=vararg_callback, dest="extra_plugin", help="build an external plugin as shared library, takes an optional include dir", metavar="PLUGIN [NAME]")
|
||||
parser.add_option("-c", "--clean", action="store_true", dest="clean", help="clean the build")
|
||||
parser.add_option("-e", "--check", action="store_true", dest="check", help="run cppcheck")
|
||||
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", help="more verbose build")
|
||||
@@ -1446,13 +1484,16 @@ if __name__ == "__main__":
|
||||
print("*** uWSGI building and linking plugin %s ***" % options.plugin[0] )
|
||||
build_plugin(options.plugin[0], uc, cflags, ldflags, libs, name)
|
||||
elif options.extra_plugin:
|
||||
print("*** uWSGI building and linking plugin ***")
|
||||
cflags = spcall("%s --cflags" % options.extra_plugin[0]).split()
|
||||
print("*** uWSGI building and linking plugin from %s ***" % options.extra_plugin[0])
|
||||
cflags = os.environ['UWSGI_PLUGINS_BUILDER_CFLAGS'].split() + os.environ.get("CFLAGS", "").split()
|
||||
cflags.append('-I.uwsgi_plugins_builder/')
|
||||
ldflags = os.environ.get("LDFLAGS", "").split()
|
||||
name = None
|
||||
try:
|
||||
cflags.append('-I%s' % options.extra_plugin[1])
|
||||
name = options.extra_plugin[1]
|
||||
except:
|
||||
pass
|
||||
build_plugin('.', None, cflags, [], [], None)
|
||||
build_plugin(options.extra_plugin[0], None, cflags, ldflags, None, name)
|
||||
elif options.clean:
|
||||
os.system("rm -f core/*.o")
|
||||
os.system("rm -f proto/*.o")
|
||||
@@ -1460,6 +1501,7 @@ if __name__ == "__main__":
|
||||
os.system("rm -f plugins/*/*.o")
|
||||
os.system("rm -f build/*.o")
|
||||
os.system("rm -f core/dot_h.c")
|
||||
os.system("rm -f core/config_py.c")
|
||||
elif options.check:
|
||||
os.system("cppcheck --max-configs=1000 --enable=all -q core/ plugins/ proto/ lib/ apache2/")
|
||||
else:
|
||||
|
||||
Reference in New Issue
Block a user