Compare commits

..
25 Commits
Author SHA1 Message Date
Unbit fe8ee7c7b3 uWSGI 1.9.4 2013-03-30 16:29:51 +01:00
Unbit cd382c6bc0 added rpcblob/rpcnext 2013-03-30 16:06:47 +01:00
Unbit e68296c293 a bit of cosmetic for uwsgi.h 2013-03-30 09:28:06 +01:00
Unbit cc189feae5 added uwsgi_register_signal to v8 2013-03-30 09:25:50 +01:00
unbit 18e19027a1 Merge pull request #207 from prymitive/legion_api
refactored legion opt functions to be more plugin friendly
2013-03-30 00:58:46 -07:00
Łukasz Mierzwa 2d2e0e4757 refactored legion opt functions to be more plugin friendly 2013-03-29 23:33:33 +01:00
Unbit a9f50d79f9 start 1.9.4 2013-03-29 21:24:56 +01:00
Unbit 0ccd31bee0 fixed reloading when in Go mode 2013-03-29 21:24:41 +01:00
Unbit 3ea82b2bcd do not differentiate reload when uWSGI is build as shared library 2013-03-29 21:21:46 +01:00
Unbit 6dad7b3ced ported the cplusplus plugin to the new api 2013-03-29 19:43:03 +01:00
Unbit f96ebd2b07 Merge branch 'master' of github.com:unbit/uwsgi 2013-03-29 19:37:53 +01:00
Unbit b8d0e7a3ac beta quality v8 plugin 2013-03-29 19:37:33 +01:00
unbit 14cca3d497 Merge pull request #204 from prymitive/legion_join_hook
legion join hook
2013-03-29 06:02:42 -07:00
Łukasz Mierzwa c343ca0cc3 legion join hook 2013-03-29 14:01:02 +01:00
Unbit 527d371bda fixed multiple mules event handling 2013-03-29 13:34:48 +01:00
Unbit b87a800a9a avoid resetting uwsgi.mywid in the master 2013-03-29 13:24:33 +01:00
Unbit e406993ed1 fixed typo 2013-03-29 12:51:52 +01:00
Unbit eeff935fc9 fixed signal handling in non-workers 2013-03-29 12:50:56 +01:00
Unbit 0791394f1a official support for SmartOS 2013-03-29 08:12:58 +00:00
unbit 082a407b06 Merge pull request #201 from prymitive/cache_restore_items_count
update cache items count after restore
2013-03-28 15:23:22 -07:00
Łukasz Mierzwa 8a89b49df1 update cache items count after restore 2013-03-28 23:20:17 +01:00
unbit 2314b9cbab Merge pull request #200 from jbert/master
Fix segfault in psgi plugin
2013-03-28 15:02:26 -07:00
John Berthels d0cca85c83 fix segfault in psgi handler after taking early-exit error path in coroae_accept_request 2013-03-28 17:29:00 +00:00
unbit 6a7a5cbcba Merge pull request #199 from prymitive/cache_stats_missin_list_close
missing list close in cache stats
2013-03-28 09:28:02 -07:00
Łukasz Mierzwa ecccc82cc8 missing list close 2013-03-28 16:56:31 +01:00
21 changed files with 484 additions and 89 deletions
+2 -1
View File
@@ -533,7 +533,8 @@ void uwsgi_cache_fix(struct uwsgi_cache *uc) {
}
}
uwsgi_log("[uwsgi-cache] restored %llu items\n", restored);
uc->n_items = restored;
uwsgi_log("[uwsgi-cache] restored %llu items\n", uc->n_items);
}
int uwsgi_cache_set2(struct uwsgi_cache *uc, char *key, uint16_t keylen, char *val, uint64_t vallen, uint64_t expires, uint64_t flags) {
+14 -14
View File
@@ -260,7 +260,7 @@ int event_queue_del_fd(int eq, int fd, int event) {
int event_queue_fd_write_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -271,7 +271,7 @@ int event_queue_fd_write_to_read(int eq, int fd) {
int event_queue_fd_read_to_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -282,7 +282,7 @@ int event_queue_fd_read_to_write(int eq, int fd) {
int event_queue_fd_readwrite_to_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -293,7 +293,7 @@ int event_queue_fd_readwrite_to_read(int eq, int fd) {
int event_queue_fd_readwrite_to_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -304,7 +304,7 @@ int event_queue_fd_readwrite_to_write(int eq, int fd) {
int event_queue_fd_write_to_readwrite(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -315,7 +315,7 @@ int event_queue_fd_write_to_readwrite(int eq, int fd) {
int event_queue_fd_read_to_readwrite(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN | POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -351,7 +351,7 @@ int event_queue_interesting_fd_is_write(void *events, int id) {
int event_queue_add_fd_read(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLIN, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -361,7 +361,7 @@ int event_queue_add_fd_read(int eq, int fd) {
int event_queue_add_fd_write(int eq, int fd) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, NULL)) {
if (port_associate(eq, PORT_SOURCE_FD, fd, POLLOUT, (void *)((long) eq))) {
uwsgi_error("port_associate");
return -1;
}
@@ -381,7 +381,7 @@ int event_queue_interesting_fd(void *events, int id) {
}
int fd = (int) pe[id].portev_object;
int eq = (int) pe[id].portev_user;
int eq = (long) pe[id].portev_user;
if (pe[id].portev_events == POLLOUT) {
event_queue_add_fd_write(eq, fd);
@@ -423,7 +423,7 @@ int event_queue_wait_multi(int eq, int timeout, void *events, int nevents) {
port_event_t *pe_i = &pe[i];
if (pe_i->portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, NULL)) {
if (port_associate(eq, pe_i->portev_source, pe_i->portev_object, pe_i->portev_events, (void *)((long) eq))) {
uwsgi_error("port_associate");
}
}
@@ -449,16 +449,16 @@ int event_queue_wait(int eq, int timeout, int *interesting_fd) {
ret = port_get(eq, &pe, NULL);
}
if (ret < 0) {
if (errno != ETIME) {
if (errno == ETIME) return 0;
if (errno != EINTR) {
uwsgi_error("port_get()");
return -1;
}
return 0;
return -1;
}
if (pe.portev_source == PORT_SOURCE_FD) {
// event must be readded (damn Oracle/Sun why the fu*k you made such a horrible choice ???? why not adding a ONESHOT flag ???)
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, NULL)) {
if (port_associate(eq, pe.portev_source, pe.portev_object, pe.portev_events, (void *)((long) eq))) {
uwsgi_error("port_associate");
}
}
+64 -24
View File
@@ -203,7 +203,6 @@ static void legions_check_nodes() {
struct uwsgi_legion_node *node = legion->nodes_head;
while (node) {
if (now - node->last_seen > uwsgi.legion_tolerance) {
struct uwsgi_legion_node *tmp_node = node;
node = node->next;
@@ -302,6 +301,18 @@ static void legions_check_nodes_step2() {
// we have quorum !!!
if (votes > 0 && votes >= ul->quorum) {
if (!ul->joined) {
// triggering join hooks
struct uwsgi_string_list *usl = ul->join_hooks;
while (usl) {
int ret = uwsgi_legion_action_call("join", ul, usl);
if (ret) {
uwsgi_log("[uwsgi-legion] ERROR, join hook returned: %d\n", ret);
}
usl = usl->next;
}
ul->joined = 1;
}
// something changed ???
if (ul->changed) {
legions_report_quorum(ul, best_valor, best_uuid, votes);
@@ -763,15 +774,20 @@ void uwsgi_opt_legion_node(char *opt, char *value, void *foobar) {
exit(1);
}
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, space + 1);
char *port = strchr(usl->value, ':');
uwsgi_legion_register_node(ul, space + 1);
}
void uwsgi_legion_register_node(struct uwsgi_legion *ul, char *addr) {
struct uwsgi_string_list *usl = uwsgi_string_new_list(&ul->nodes, addr);
char *port = strchr(addr, ':');
if (!port) {
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", usl->value);
uwsgi_log("[uwsgi-legion] invalid udp address: %s\n", addr);
exit(1);
}
// no need to zero the memory, socket_to_in_addr will do that
struct sockaddr_in *sin = uwsgi_malloc(sizeof(struct sockaddr_in));
usl->custom = socket_to_in_addr(usl->value, port, 0, sin);
usl->custom = socket_to_in_addr(addr, port, 0, sin);
usl->custom_ptr = sin;
}
@@ -823,51 +839,69 @@ void uwsgi_opt_legion_scroll(char *opt, char *value, void *foobar) {
void uwsgi_opt_legion_hook(char *opt, char *value, void *foobar) {
char *event = strchr(opt, '-');
if (!event) {
uwsgi_log("[uwsgi-legion] invalid option name (%s), this should not happen (possible bug)\n", opt);
exit(1);
}
char *legion = uwsgi_str(value);
char *space = strchr(legion, ' ');
if (!space) {
uwsgi_log("invalid %s syntax, must be <legion> <action>\n", opt);
uwsgi_log("[uwsgi-legion] invalid %s syntax, must be <legion> <action>\n", opt);
exit(1);
}
*space = 0;
struct uwsgi_legion *ul = uwsgi_legion_get_by_name(legion);
if (!ul) {
uwsgi_log("unknown legion: %s\n", legion);
uwsgi_log("[uwsgi-legion] unknown legion: %s\n", legion);
exit(1);
}
uwsgi_legion_register_hook(ul, event + 1, space + 1);
}
void uwsgi_legion_register_hook(struct uwsgi_legion *ul, char *event, char *action) {
struct uwsgi_string_list *usl = NULL;
if (!strcmp(opt, "legion-lord")) {
usl = uwsgi_string_new_list(&ul->lord_hooks, space + 1);
if (!strcmp(event, "lord")) {
usl = uwsgi_string_new_list(&ul->lord_hooks, action);
}
else if (!strcmp(opt, "legion-unlord")) {
usl = uwsgi_string_new_list(&ul->unlord_hooks, space + 1);
else if (!strcmp(event, "unlord")) {
usl = uwsgi_string_new_list(&ul->unlord_hooks, action);
}
else if (!strcmp(opt, "legion-setup")) {
usl = uwsgi_string_new_list(&ul->setup_hooks, space + 1);
else if (!strcmp(event, "setup")) {
usl = uwsgi_string_new_list(&ul->setup_hooks, action);
}
else if (!strcmp(opt, "legion-death")) {
usl = uwsgi_string_new_list(&ul->death_hooks, space + 1);
else if (!strcmp(event, "death")) {
usl = uwsgi_string_new_list(&ul->death_hooks, action);
}
else if (!strcmp(event, "join")) {
usl = uwsgi_string_new_list(&ul->join_hooks, action);
}
else {
uwsgi_log("[uwsgi-legion] invalid event: %s\n", event);
exit(1);
}
if (!usl)
return;
char *port = strchr(usl->value, ':');
if (!port) {
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", opt, usl->value);
char *hook = strchr(action, ':');
if (!hook) {
uwsgi_log("[uwsgi-legion] invalid %s action: %s\n", event, action);
exit(1);
}
// pointer to action plugin
usl->custom_ptr = uwsgi_concat2n(usl->value, port - usl->value, "", 0);
usl->custom_ptr = uwsgi_concat2n(action, hook - action, "", 0);;
// add that to check the plugin value
usl->custom = port - usl->value + 1;
}
usl->custom = hook - action + 1;
}
void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
@@ -905,6 +939,10 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
*colon = 0;
char *secret = colon + 1;
uwsgi_legion_register(legion, addr, valor, algo_secret, secret);
}
struct uwsgi_legion *uwsgi_legion_register(char *legion, char *addr, char *valor, char *algo, char *secret) {
char *iv = strchr(secret, ' ');
if (iv) {
*iv = 0;
@@ -918,9 +956,9 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
EVP_CIPHER_CTX *ctx = uwsgi_malloc(sizeof(EVP_CIPHER_CTX));
EVP_CIPHER_CTX_init(ctx);
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo_secret);
const EVP_CIPHER *cipher = EVP_get_cipherbyname(algo);
if (!cipher) {
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo_secret);
uwsgi_log("[uwsgi-legion] unable to find algorithm/cipher %s\n", algo);
exit(1);
}
@@ -983,6 +1021,8 @@ void uwsgi_opt_legion(char *opt, char *value, void *foobar) {
ul->scrolls = uwsgi_calloc_shared(ul->scrolls_max_size);
uwsgi_legion_add(ul);
return ul;
}
struct uwsgi_legion_action *uwsgi_legion_action_get(char *name) {
+19 -19
View File
@@ -798,8 +798,8 @@ int master_loop(char **argv, char **environ) {
*/
uwsgi.mywid = find_worker_id(diedpid);
if (uwsgi.mywid <= 0) {
int thewid = find_worker_id(diedpid);
if (thewid <= 0) {
// check spooler, mules, gateways and daemons
struct uwsgi_spooler *uspool = uwsgi.spoolers;
while (uspool) {
@@ -842,50 +842,50 @@ next:
// ok a worker died...
uwsgi.workers[uwsgi.mywid].pid = 0;
uwsgi.workers[thewid].pid = 0;
// only to be safe :P
uwsgi.workers[uwsgi.mywid].harakiri = 0;
uwsgi.workers[thewid].harakiri = 0;
// ok, if we are reloading or dying, just continue the master loop
// as soon as all of the workers have pid == 0, the action (exit, or reload) is triggered
if (uwsgi_instance_is_reloading || uwsgi_instance_is_dying) {
uwsgi_log("worker %d buried after %d seconds\n", uwsgi.mywid, (int) (uwsgi_now()-uwsgi.workers[uwsgi.mywid].cursed_at));
uwsgi.workers[uwsgi.mywid].cursed_at = 0;
uwsgi_log("worker %d buried after %d seconds\n", thewid, (int) (uwsgi_now()-uwsgi.workers[thewid].cursed_at));
uwsgi.workers[thewid].cursed_at = 0;
continue;
}
// if we are stopping workers, just end here
if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_FAILED_APP_CODE) {
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("OOPS ! failed loading app in worker %d (pid %d) :( trying again...\n", thewid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_DE_HIJACKED_CODE) {
uwsgi_log("...restoring worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("...restoring worker %d (pid: %d)...\n", thewid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_EXCEPTION_CODE) {
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("... monitored exception detected, respawning worker %d (pid: %d)...\n", thewid, (int) diedpid);
}
else if (WIFEXITED(waitpid_status) && WEXITSTATUS(waitpid_status) == UWSGI_QUIET_CODE) {
// noop
}
else if (uwsgi.workers[uwsgi.mywid].manage_next_request) {
else if (uwsgi.workers[thewid].manage_next_request) {
if (WIFSIGNALED(waitpid_status)) {
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
uwsgi_log("DAMN ! worker %d (pid: %d) died, killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
}
else {
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", uwsgi.mywid, (int) diedpid);
uwsgi_log("DAMN ! worker %d (pid: %d) died :( trying respawn ...\n", thewid, (int) diedpid);
}
}
else if (uwsgi.workers[uwsgi.mywid].cursed_at > 0) {
uwsgi_log("worker %d killed successfully (pid: %d)\n", uwsgi.mywid, (int) diedpid);
else if (uwsgi.workers[thewid].cursed_at > 0) {
uwsgi_log("worker %d killed successfully (pid: %d)\n", thewid, (int) diedpid);
}
// manage_next_request is zero, but killed by signal...
else if (WIFSIGNALED(waitpid_status)) {
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", uwsgi.mywid, (int) diedpid, (int) WTERMSIG(waitpid_status));
uwsgi_log("DAMN ! worker %d (pid: %d) MISTERIOUSLY killed by signal %d :( trying respawn ...\n", thewid, (int) diedpid, (int) WTERMSIG(waitpid_status));
}
if (uwsgi.workers[uwsgi.mywid].cheaped == 1) {
uwsgi_log("uWSGI worker %d cheaped.\n", uwsgi.mywid);
if (uwsgi.workers[thewid].cheaped == 1) {
uwsgi_log("uWSGI worker %d cheaped.\n", thewid);
continue;
}
@@ -909,12 +909,12 @@ next:
uwsgi.respawn_delta = last_respawn.tv_sec;
// are we chain reloading it ?
if (uwsgi.status.chain_reloading == uwsgi.mywid) {
if (uwsgi.status.chain_reloading == thewid) {
uwsgi.status.chain_reloading++;
}
// respawn the worker (if needed)
if (uwsgi_respawn_worker(uwsgi.mywid))
if (uwsgi_respawn_worker(thewid))
return 0;
// end of the loop
+3 -4
View File
@@ -413,9 +413,6 @@ void uwsgi_reload(char **argv) {
#endif
}
#ifdef UWSGI_AS_SHARED_LIBRARY
return;
#else
uwsgi_log("running %s\n", uwsgi.binary_path);
uwsgi_flush_logs();
argv[0] = uwsgi.binary_path;
@@ -436,7 +433,6 @@ void uwsgi_reload(char **argv) {
uwsgi_error("execvp()");
// never here
exit(1);
#endif
}
@@ -957,6 +953,9 @@ struct uwsgi_stats *uwsgi_master_generate_stats() {
uc = uc->next;
}
if (uwsgi_stats_list_close(us))
goto end;
if (uwsgi_stats_comma(us))
goto end;
}
+6 -2
View File
@@ -184,6 +184,7 @@ void uwsgi_mule_handler() {
if (interesting_fd == uwsgi.signal_socket || interesting_fd == uwsgi.my_signal_socket || farm_has_signaled(interesting_fd)) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) continue;
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
@@ -197,7 +198,9 @@ void uwsgi_mule_handler() {
else if (interesting_fd == uwsgi.mules[uwsgi.muleid - 1].queue_pipe[1] || interesting_fd == uwsgi.shared->mule_queue_pipe[1] || farm_has_msg(interesting_fd)) {
len = read(interesting_fd, message, 65536);
if (len < 0) {
uwsgi_error("read()");
if (errno != EAGAIN && errno != EINTR && errno != EWOULDBLOCK) {
uwsgi_error("uwsgi_mule_handler/read()");
}
}
else {
int i, found = 0;
@@ -343,6 +346,7 @@ next:
if (interesting_fd > -1) {
len = read(interesting_fd, &uwsgi_signal, 1);
if (len <= 0) {
if (len < 0 && (errno == EAGAIN || errno == EINTR || errno == EWOULDBLOCK)) goto clear;
uwsgi_log_verbose("uWSGI mule %d braying: my master died, i will follow him...\n", uwsgi.muleid);
end_me(0);
}
@@ -350,7 +354,7 @@ next:
uwsgi_log_verbose("master sent signal %d to mule %d\n", uwsgi_signal, uwsgi.muleid);
#endif
if (uwsgi_signal_handler(uwsgi_signal)) {
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.mywid);
uwsgi_log_verbose("error managing signal %d on mule %d\n", uwsgi_signal, uwsgi.muleid);
}
// set the error condition
len = -1;
+3 -1
View File
@@ -260,6 +260,8 @@ int uwsgi_add_probe(uint8_t sig, char *kind, char *args, int timeout, int freq)
int uwsgi_add_timer(uint8_t sig, int secs) {
if (!uwsgi.master_process) return -1;
uwsgi_lock(uwsgi.timer_table_lock);
if (ushared->timers_cnt < 64) {
@@ -595,7 +597,7 @@ void uwsgi_receive_signal(int fd, char *name, int id) {
if (ret == 0) {
goto destroy;
}
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
else if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK && errno != EINTR) {
uwsgi_error("[uwsgi-signal] read()");
goto destroy;
}
-1
View File
@@ -108,7 +108,6 @@ pid_t spooler_start(struct uwsgi_spooler * uspool) {
signal(SIGSTOP, SIG_IGN);
signal(SIGTSTP, SIG_IGN);
uwsgi.mywid = -1;
uwsgi.mypid = getpid();
uspool->pid = uwsgi.mypid;
// avoid race conditions !!!
+1
View File
@@ -383,6 +383,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
{"legion-unlord", required_argument, 0, "action to call on Lord dismiss", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-setup", required_argument, 0, "action to call on legion setup", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-death", required_argument, 0, "action to call on legion death (shutdown of the instance)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-join", required_argument, 0, "action to call on legion join (first time quorum is reached)", uwsgi_opt_legion_hook, NULL, UWSGI_OPT_MASTER},
{"legion-quorum", required_argument, 0, "set the quorum of a legion", uwsgi_opt_legion_quorum, NULL, UWSGI_OPT_MASTER},
{"legion-scroll", required_argument, 0, "set the scroll of a legion", uwsgi_opt_legion_scroll, NULL, UWSGI_OPT_MASTER},
{"legion-scroll-max-size", required_argument, 0, "set max size of legion scroll buffer", uwsgi_opt_set_16bit, &uwsgi.legion_scroll_max_size, 0},
+6 -4
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
extern struct uwsgi_server uwsgi;
@@ -13,8 +13,9 @@ class FakeClass {
void FakeClass::hello_world(struct wsgi_request *wsgi_req) {
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, (char *) "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n", 44);
wsgi_req->response_size += wsgi_req->socket->proto_write(wsgi_req, foobar, foobar_len);
uwsgi_response_prepare_headers(wsgi_req, (char *)"200 OK", 6);
uwsgi_response_add_content_type(wsgi_req, (char *)"text/html", 9);
uwsgi_response_write_body_do(wsgi_req, foobar, foobar_len);
}
extern "C" int uwsgi_cplusplus_init(){
@@ -27,7 +28,7 @@ extern "C" int uwsgi_cplusplus_request(struct wsgi_request *wsgi_req) {
FakeClass *fc;
// empty request ?
if (!wsgi_req->uh.pktsize) {
if (!wsgi_req->uh->pktsize) {
uwsgi_log( "Invalid request. skip.\n");
goto clear;
}
@@ -55,6 +56,7 @@ clear:
extern "C" void uwsgi_cplusplus_after_request(struct wsgi_request *wsgi_req) {
// call log_request(wsgi_req) if you want a standard logline
uwsgi_log("logging c++ request\n");
}
+1 -1
View File
@@ -1,4 +1,4 @@
#include "../../uwsgi.h"
#include <uwsgi.h>
int uwsgi_cplusplus_init(void);
+1
View File
@@ -722,6 +722,7 @@ static void uwsgi_lua_configurator(char *filename, char *magic_table[]) {
uwsgi_log("error running Lua configurator: %s\n", lua_tostring(L, -1));
exit(1);
}
free(code);
if (!lua_istable(L, -1)) {
uwsgi_log("Lua configurator has to return a table !!!\n");
+5 -1
View File
@@ -513,6 +513,10 @@ void uwsgi_perl_after_request(struct wsgi_request *wsgi_req) {
log_request(wsgi_req);
// We may be called after an early exit in XS_coroae_accept_request,
// before the environ is set up.
if (!wsgi_req->async_environ) return;
// dereference %env
SV *env = SvRV((SV *) wsgi_req->async_environ);
@@ -664,7 +668,7 @@ void uwsgi_perl_run_hook(SV *hook) {
}
static void uwsgi_perl_atexit() {
if (uwsgi.mywid == -1) goto realstuff;
if (uwsgi.mywid == 0) goto realstuff;
// if hijacked do not run atexit hooks
if (uwsgi.workers[uwsgi.mywid].hijacked)
+1 -1
View File
@@ -290,7 +290,7 @@ void uwsgi_python_reset_random_seed() {
void uwsgi_python_atexit() {
if (uwsgi.mywid == -1) goto realstuff;
if (uwsgi.mywid == 0) goto realstuff;
// if hijacked do not run atexit hooks
if (uwsgi.workers[uwsgi.mywid].hijacked)
+64
View File
@@ -93,6 +93,62 @@ end:
return ret;
}
static int uwsgi_routing_func_rpc_blob(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int ret = -1;
// this is the list of args
char *argv[UMAX8];
// this is the size of each argument
uint16_t argvs[UMAX8];
// this is a placeholder for tmp uwsgi_buffers
struct uwsgi_buffer *ubs[UMAX8];
char **r_argv = (char **) ur->data2;
uint16_t *r_argvs = (uint16_t *) ur->data3;
char **subject = (char **) (((char *)(wsgi_req))+ur->subject);
uint16_t *subject_len = (uint16_t *) (((char *)(wsgi_req))+ur->subject_len);
uint64_t i;
for(i=0;i<ur->custom;i++) {
ubs[i] = uwsgi_routing_translate(wsgi_req, ur, *subject, *subject_len, r_argv[i], r_argvs[i]);
if (!ubs[i]) goto end;
argv[i] = ubs[i]->buf;
argvs[i] = ubs[i]->pos;
}
// ok we now need to check it it is a local call or a remote one
char *func = uwsgi_str(ur->data);
char *remote = NULL;
char *at = strchr(func, '@');
if (at) {
*at = 0;
remote = at+1;
}
uint16_t size;
char *response = uwsgi_do_rpc(remote, func, ur->custom, argv, argvs, &size);
free(func);
if (!response) goto end;
ret = UWSGI_ROUTE_NEXT;
// optimization
if (!wsgi_req->headers_sent) {
if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6)) {free(response) ; goto end;}
if (uwsgi_response_add_connection_close(wsgi_req)) {free(response) ; goto end;}
}
uwsgi_response_write_body_do(wsgi_req, response, size);
free(response);
end:
for(i=0;i<ur->custom;i++) {
if (ubs[i] != NULL) {
uwsgi_buffer_destroy(ubs[i]);
}
}
return ret;
}
// "next" || "continue" || "break(.*)" || "goon" || "goto .+"
static int uwsgi_routing_func_rpc_ret(struct wsgi_request *wsgi_req, struct uwsgi_route *ur) {
int ret = -1;
@@ -238,10 +294,18 @@ static int uwsgi_router_rpc_ret(struct uwsgi_route *ur, char *args) {
return uwsgi_router_rpc_base(ur, args);
}
static int uwsgi_router_rpc_blob(struct uwsgi_route *ur, char *args) {
ur->func = uwsgi_routing_func_rpc_blob;
return uwsgi_router_rpc_base(ur, args);
}
static void router_rpc_register() {
uwsgi_register_router("call", uwsgi_router_rpc);
uwsgi_register_router("rpc", uwsgi_router_rpc);
uwsgi_register_router("rpcret", uwsgi_router_rpc_ret);
uwsgi_register_router("rpcblob", uwsgi_router_rpc_blob);
uwsgi_register_router("rpcnext", uwsgi_router_rpc_blob);
}
#endif
+29
View File
@@ -0,0 +1,29 @@
#include <uwsgi.h>
int uwsgi_v8_init(void);
void uwsgi_v8_apps(void);
void uwsgi_v8_configurator(char *, char **);
uint16_t uwsgi_v8_rpc(void *, uint8_t, char **, uint16_t *, char *);
int uwsgi_v8_signal_handler(uint8_t, void *);
static void uwsgi_v8_register(void) {
uwsgi_register_configurator(".js", uwsgi_v8_configurator);
}
extern struct uwsgi_option uwsgi_v8_options[];
static int uwsgi_v8_request(struct wsgi_request *wsgi_req) {
return UWSGI_OK;
}
struct uwsgi_plugin v8_plugin = {
.name = "v8",
.modifier1 = 24,
.init = uwsgi_v8_init,
.init_apps = uwsgi_v8_apps,
.options = uwsgi_v8_options,
.on_load = uwsgi_v8_register,
.rpc = uwsgi_v8_rpc,
.request = uwsgi_v8_request,
.signal_handler = uwsgi_v8_signal_handler,
};
+6
View File
@@ -0,0 +1,6 @@
NAME='v8'
CFLAGS = []
LDFLAGS = []
LIBS = ['-lv8']
GCC_LIST = ['plugin', 'v8_uwsgi.cc']
+237
View File
@@ -0,0 +1,237 @@
#include <uwsgi.h>
#include <v8.h>
struct uwsgi_v8 {
v8::Persistent<v8::Context> *contexts;
struct uwsgi_string_list *load;
} uv8;
extern struct uwsgi_server uwsgi;
extern struct uwsgi_plugin v8_plugin;
struct uwsgi_option uwsgi_v8_options[] = {
{(char *)"v8-load", required_argument, 0, (char *)"load a javascript file", uwsgi_opt_add_string_list, &uv8.load, 0},
{0, 0, 0, 0},
};
static v8::Handle<v8::Value> uwsgi_v8_api_register_signal(const v8::Arguments& args) {
if (args.Length() > 2) {
uint8_t uwsgi_signal = args[0]->Uint32Value();
v8::String::Utf8Value signal_kind(args[1]->ToString());
v8::Persistent<v8::Function> func = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(args[2]));
if (uwsgi_register_signal(uwsgi_signal, *signal_kind, *func, v8_plugin.modifier1)) {
uwsgi_log("[uwsgi-v8] unable to register signal %d\n", uwsgi_signal);
return v8::Undefined();
}
return v8::True();
}
return v8::Undefined();
}
static v8::Handle<v8::Value> uwsgi_v8_api_register_rpc(const v8::Arguments& args) {
if (args.Length() > 1) {
v8::String::Utf8Value name(args[0]->ToString());
uint8_t j_argc = 0;
if (args.Length() > 2) {
j_argc = args[2]->Uint32Value();
}
v8::Persistent<v8::Function> func = v8::Persistent<v8::Function>::New(v8::Handle<v8::Function>::Cast(args[1]));
if (uwsgi_register_rpc(*name, v8_plugin.modifier1, j_argc, *func)) {
uwsgi_log("[uwsgi-v8] unable to register RPC function \"%s\"\n", *name);
return v8::Undefined();
}
return v8::True();
}
return v8::Undefined();
}
static void uwsgi_v8_load_file(v8::Persistent<v8::Context> context, char *filename) {
v8::HandleScope handle_scope;
v8::Context::Scope context_scope(context);
size_t len = 0;
char *code = uwsgi_open_and_read(filename, &len, 1, NULL);
// we do not use TryCatch as we directly use stderr and simply exit with error code 1
v8::Handle<v8::Script> script = v8::Script::Compile( v8::String::New(code), v8::String::New(filename) );
free(code);
if (script.IsEmpty()) {
exit(1);
}
v8::Handle<v8::Value> result = script->Run();
if (result.IsEmpty()) {
exit(1);
}
}
extern "C" int uwsgi_v8_init(){
uwsgi_log("Initializing V8 %s environment... (%d Isolates)\n", v8::V8::GetVersion(), uwsgi.cores);
uv8.contexts = (v8::Persistent<v8::Context> *) uwsgi_malloc( sizeof(v8::Persistent<v8::Context>*) * uwsgi.cores );
return 0;
}
static v8::Handle<v8::Value> uwsgi_v8_api_log(const v8::Arguments& args) {
if (args.Length() > 0) {
v8::String::Utf8Value str(args[0]->ToString());
size_t slen = strlen(*str);
if ((*str)[slen-1] == '\n') {
uwsgi_log("%s", *str);
}
else {
uwsgi_log("%s\n", *str);
}
}
return v8::Undefined();
}
static v8::Persistent<v8::Context> uwsgi_v8_new_isolate(int core) {
v8::HandleScope handle_scope;
if (core > 0) {
// create a new isolate
v8::Isolate *isolate = v8::Isolate::New();
// set as the current isolate
v8::Isolate::Scope iscope(isolate);
}
v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New();
// print alias is always handy
global->Set(v8::String::New("uwsgi_log"), v8::FunctionTemplate::New(uwsgi_v8_api_log));
global->Set(v8::String::New("uwsgi_register_rpc"), v8::FunctionTemplate::New(uwsgi_v8_api_register_rpc));
global->Set(v8::String::New("uwsgi_register_signal"), v8::FunctionTemplate::New(uwsgi_v8_api_register_signal));
// create a new context
v8::Persistent<v8::Context> context = v8::Context::New(NULL, global);
return context;
}
extern "C" void uwsgi_v8_apps() {
if (!uv8.load) return;
int i;
for(i=0;i<uwsgi.cores;i++) {
uv8.contexts[i] = uwsgi_v8_new_isolate(i);
struct uwsgi_string_list *usl = uv8.load;
while(usl) {
uwsgi_v8_load_file(uv8.contexts[i], usl->value);
usl = usl->next;
}
}
}
extern "C" void uwsgi_v8_configurator(char *filename, char *magic_table[]) {
v8::HandleScope handle_scope;
uwsgi_log_initial("[uWSGI] getting javascript (V8) configuration from %s\n", filename);
size_t len = 0;
char *code = uwsgi_open_and_read(filename, &len, 1, NULL);
v8::Handle<v8::Context> context = v8::Context::New();
v8::Context::Scope context_scope(context);
// we do not use TryCatch as we directly use stderr and simply exit with error code 1
v8::Handle<v8::Script> script = v8::Script::Compile( v8::String::New(code), v8::String::New(filename) );
if (script.IsEmpty()) {
exit(1);
}
free(code);
v8::Handle<v8::Value> result = script->Run();
if (result.IsEmpty()) {
exit(1);
}
if (!result->IsArray() && !result->IsObject()) {
uwsgi_log("javascript return value must be an object or an array !!!\n");
exit(1);
}
uint32_t i;
const v8::Local<v8::Array> props = result->ToObject()->GetPropertyNames();
const uint32_t l = props->Length();
for(i=0;i<l;i++) {
const v8::Local<v8::Value> key = props->Get(i);
const v8::Local<v8::Value> value = result->ToObject()->Get(key);
v8::String::Utf8Value c_key(key->ToString());
if (value->IsArray()) {
uint32_t opt_l = value->ToObject()->Get(v8::String::New("length"))->ToObject()->Uint32Value();
uint32_t j;
for(j=0;j<opt_l;j++) {
v8::String::Utf8Value c_value(value->ToObject()->Get(j)->ToString());
add_exported_option(uwsgi_str(*c_key), uwsgi_str(*c_value), 0);
}
}
else {
v8::String::Utf8Value c_value(value->ToString());
add_exported_option(uwsgi_str(*c_key), uwsgi_str(*c_value), 0);
}
}
}
extern "C" uint16_t uwsgi_v8_rpc(void * func, uint8_t argc, char **argv, uint16_t argvs[], char *buffer) {
v8::HandleScope handle_scope;
v8::Handle<v8::Value> argj[256];
struct wsgi_request *wsgi_req = current_wsgi_req();
v8::Context::Scope context_scope(uv8.contexts[wsgi_req->async_id]);
v8::Persistent<v8::Function> l_func = static_cast<v8::Function*> (func);
uint8_t i;
for(i=0;i<argc;i++) {
argj[i] = v8::String::New(argv[i], argvs[i]);
}
v8::Handle<v8::Value> result = l_func->Call(l_func, argc, argj);
if (result.IsEmpty()) return 0;
v8::Handle<v8::String> robj = result->ToString();
v8::String::Utf8Value r_value(robj);
if (!*robj) return 0;
uint16_t rlen = robj->Length();
memcpy(buffer, *r_value, rlen);
// call GC every time, could be overkill, we should allow to tune that choice
while(!v8::V8::IdleNotification()) {};
return rlen;
}
extern "C" int uwsgi_v8_signal_handler(uint8_t sig, void *handler) {
int ret = 0;
v8::HandleScope handle_scope;
struct wsgi_request *wsgi_req = current_wsgi_req();
v8::Context::Scope context_scope(uv8.contexts[wsgi_req->async_id]);
v8::Persistent<v8::Function> l_func = static_cast<v8::Function*> (handler);
v8::Handle<v8::Value> argj[1];
argj[0] = v8::Number::New(sig);
v8::Handle<v8::Value> result = l_func->Call(l_func, 1, argj);
if (result.IsEmpty()) ret = -1;
while(!v8::V8::IdleNotification()) {};
return ret;
}
+1 -1
View File
@@ -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-03-28'
s.date = '2013-03-30'
s.summary = "uWSGI"
s.description = "The uWSGI server for Ruby/Rack"
s.authors = ["Unbit"]
+20 -14
View File
@@ -597,6 +597,9 @@ struct uwsgi_legion_node {
int quorum;
int changed;
// set to 1 first time when quorum is reached
int joined;
uint64_t checksum;
char *scroll;
@@ -634,6 +637,7 @@ struct uwsgi_legion_node {
struct uwsgi_string_list *unlord_hooks;
struct uwsgi_string_list *setup_hooks;
struct uwsgi_string_list *death_hooks;
struct uwsgi_string_list *join_hooks;
struct uwsgi_legion *next;
};
@@ -832,9 +836,9 @@ struct uwsgi_cache {
struct uwsgi_loop *next;
};
struct wsgi_request;
struct wsgi_request;
struct uwsgi_socket {
struct uwsgi_socket {
int fd;
char *name;
int name_len;
@@ -904,11 +908,11 @@ struct uwsgi_cache {
int lazy;
int shared;
int from_shared;
};
};
struct uwsgi_server;
struct uwsgi_server;
struct uwsgi_plugin {
struct uwsgi_plugin {
const char *name;
const char *alias;
@@ -949,7 +953,7 @@ struct uwsgi_cache {
int (*spooler) (char *, char *, uint16_t, char *, size_t);
uint16_t(*rpc) (void *, uint8_t, char **, uint16_t *, char *);
uint16_t(*rpc) (void *, uint8_t, char **, uint16_t *, char *);
void (*jail) (int (*)(void *), char **);
void (*before_privileges_drop) (void);
@@ -959,13 +963,12 @@ struct uwsgi_cache {
void (*master_cleanup) (void);
struct uwsgi_buffer* (*backtrace)(struct wsgi_request *);
struct uwsgi_buffer* (*exception_class)(struct wsgi_request *);
struct uwsgi_buffer* (*exception_msg)(struct wsgi_request *);
struct uwsgi_buffer* (*exception_repr)(struct wsgi_request *);
void (*exception_log)(struct wsgi_request *);
};
struct uwsgi_buffer* (*exception_class)(struct wsgi_request *);
struct uwsgi_buffer* (*exception_msg)(struct wsgi_request *);
struct uwsgi_buffer* (*exception_repr)(struct wsgi_request *);
void (*exception_log)(struct wsgi_request *);
};
#ifdef UWSGI_PCRE
int uwsgi_regexp_build(char *, pcre **, pcre_extra **);
@@ -3756,9 +3759,12 @@ void uwsgi_user_unlock(int);
#ifdef UWSGI_SSL
void uwsgi_opt_legion(char *, char *, void *);
struct uwsgi_legion *uwsgi_legion_register(char *, char *, char *, char *, char *);
void uwsgi_opt_legion_node(char *, char *, void *);
void uwsgi_legion_register_node(struct uwsgi_legion *, char *);
void uwsgi_opt_legion_quorum(char *, char *, void *);
void uwsgi_opt_legion_hook(char *, char *, void *);
void uwsgi_legion_register_hook(struct uwsgi_legion *, char *, char *);
void uwsgi_opt_legion_scroll(char *, char *, void *);
void uwsgi_legion_add(struct uwsgi_legion *);
char *uwsgi_ssl_rand(size_t);
@@ -3898,8 +3904,8 @@ char *uwsgi_get_header(struct wsgi_request *, char *, uint16_t, uint16_t *);
void uwsgi_alarm_thread_start(void);
void uwsgi_exceptions_handler_thread_start(void);
#define uwsgi_response_add_connection_close(x) uwsgi_response_add_header(x, "Connection", 10, "close", 5)
#define uwsgi_response_add_content_type(x, y, z) uwsgi_response_add_header(x, "Content-Type", 12, y, z)
#define uwsgi_response_add_connection_close(x) uwsgi_response_add_header(x, (char *)"Connection", 10, (char *)"close", 5)
#define uwsgi_response_add_content_type(x, y, z) uwsgi_response_add_header(x, (char *)"Content-Type", 12, y, z)
struct uwsgi_stats_pusher_instance *uwsgi_stats_pusher_add(struct uwsgi_stats_pusher *, char *);
+1 -1
View File
@@ -1,6 +1,6 @@
# uWSGI build system
uwsgi_version = '1.9.3'
uwsgi_version = '1.9.4'
import os
import re