Esempio n. 1
0
File: emperor.c Progetto: ahua/c
// this is the monitor for glob patterns
void uwsgi_imperial_monitor_glob(struct uwsgi_emperor_scanner *ues) {

	glob_t g;
	int i;
	struct stat st;
	struct uwsgi_instance *ui_current;

	if (glob(ues->arg, GLOB_MARK | GLOB_NOCHECK, NULL, &g)) {
		uwsgi_error("glob()");
		return;
	}

	for (i = 0; i < (int) g.gl_pathc; i++) {

		if (!uwsgi_emperor_is_valid(g.gl_pathv[i]))
			continue;

		if (stat(g.gl_pathv[i], &st))
			continue;

		if (!S_ISREG(st.st_mode))
			continue;

		ui_current = emperor_get(g.gl_pathv[i]);

		uid_t t_uid = st.st_uid;
                gid_t t_gid = st.st_gid;

                if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
                        struct stat lst;
                        if (lstat(g.gl_pathv[i], &lst)) {
                                uwsgi_error("[emperor-tyrant]/lstat()");
                                if (ui_current) {
                                        uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
                                        emperor_stop(ui_current);
                                }
                                continue;
                        }
                        t_uid = lst.st_uid;
                        t_gid = lst.st_gid;
                }

		if (ui_current) {
			// check if uid or gid are changed, in such case, stop the instance
			if (uwsgi.emperor_tyrant) {
				if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
					uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", g.gl_pathv[i]);
					emperor_stop(ui_current);
					continue;
				}
			}
			// check if mtime is changed and the uWSGI instance must be reloaded
			if (st.st_mtime > ui_current->last_mod) {
				emperor_respawn(ui_current, st.st_mtime);
			}
		}
		else {
			char *socket_name = emperor_check_on_demand_socket(g.gl_pathv[i]);
			emperor_add(ues, g.gl_pathv[i], st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
			if (socket_name) free(socket_name);
		}

	}
	globfree(&g);

	// now check for removed instances
	struct uwsgi_instance *c_ui = ui->ui_next;

	while (c_ui) {
		if (c_ui->scanner == ues) {
			if (c_ui->zerg) {
                                char *colon = strrchr(c_ui->name, ':');
                                if (!colon) {
                                        emperor_stop(c_ui);
                                }
                                else {
                                        char *filename = uwsgi_calloc(0xff);
                                        memcpy(filename, c_ui->name, colon - c_ui->name);
                                        if (stat(filename, &st)) {
                                                emperor_stop(c_ui);
                                        }
                                        free(filename);
                                }
                        }
                        else {
                                if (stat(c_ui->name, &st)) { 
                                        emperor_stop(c_ui);
                                }       
                        }
		}
		c_ui = c_ui->ui_next;
	}


}
Esempio n. 2
0
File: emperor.c Progetto: ahua/c
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) {

	struct uwsgi_instance *c_ui = ui;
	struct uwsgi_instance *n_ui = NULL;
	struct timeval tv;

#ifdef UWSGI_DEBUG
	uwsgi_log("\n\nVASSAL %s %d %.*s %d %d\n", name, born, config_size, config, uid, gid);
#endif

	if (strlen(name) > (0xff - 1)) {
		uwsgi_log("[emperor] invalid vassal name: %s\n", name);
		return;
	}


	gettimeofday(&tv, NULL);
	int now = tv.tv_sec;
	uint64_t micros = (tv.tv_sec * 1000 * 1000) + tv.tv_usec;

	// blacklist check
	struct uwsgi_emperor_blacklist_item *uebi = uwsgi_emperor_blacklist_check(name);
	if (uebi) {
		uint64_t i_micros = (uebi->last_attempt.tv_sec * 1000 * 1000) + uebi->last_attempt.tv_usec + uebi->throttle_level;
		if (i_micros > micros) {
			return;
		}
	}

	if (now - emperor_throttle < 1) {
		emperor_throttle_level = emperor_throttle_level * 2;
	}
	else {
		if (emperor_throttle_level > uwsgi.emperor_throttle) {
			emperor_throttle_level = emperor_throttle_level / 2;
		}

		if (emperor_throttle_level < uwsgi.emperor_throttle) {
			emperor_throttle_level = uwsgi.emperor_throttle;
		}
	}

	emperor_throttle = now;
#ifdef UWSGI_DEBUG
	uwsgi_log("emperor throttle = %d\n", emperor_throttle_level);
#endif
	usleep(emperor_throttle_level);

	if (uwsgi.emperor_tyrant) {
		if (uid == 0 || gid == 0) {
			uwsgi_log("[emperor-tyrant] invalid permissions for vassal %s\n", name);
			return;
		}
	}

	while (c_ui->ui_next) {
		c_ui = c_ui->ui_next;
	}

	n_ui = uwsgi_calloc(sizeof(struct uwsgi_instance));

	if (config) {
		n_ui->use_config = 1;
		n_ui->config = config;
		n_ui->config_len = config_size;
	}

	c_ui->ui_next = n_ui;
#ifdef UWSGI_DEBUG
	uwsgi_log("c_ui->ui_next = %p\n", c_ui->ui_next);
#endif
	n_ui->ui_prev = c_ui;

	if (strchr(name, ':')) {
		n_ui->zerg = 1;
		uwsgi.emperor_broodlord_count++;
	}

	n_ui->scanner = ues;
	memcpy(n_ui->name, name, strlen(name));
	n_ui->born = born;
	n_ui->uid = uid;
	n_ui->gid = gid;
	n_ui->last_mod = born;
	// start without loyalty
	n_ui->last_loyal = 0;
	n_ui->loyal = 0;

	n_ui->first_run = uwsgi_now();
	n_ui->last_run = n_ui->first_run;
	n_ui->on_demand_fd = -1;
	if (socket_name) {
		n_ui->socket_name = uwsgi_str(socket_name);
	}

	n_ui->pid = -1;

	// ok here we check if we need to bind to the specified socket or continue with the activation
	if (socket_name) {
		char *tcp_port = strchr(socket_name, ':');
                if (tcp_port) {
                        // disable deferred accept for this socket
                        int current_defer_accept = uwsgi.no_defer_accept;
                        uwsgi.no_defer_accept = 1;
                        n_ui->on_demand_fd = bind_to_tcp(socket_name, uwsgi.listen_queue, tcp_port);
                        uwsgi.no_defer_accept = current_defer_accept;
                }
                else {
                        n_ui->on_demand_fd = bind_to_unix(socket_name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
                }

		if (n_ui->on_demand_fd < 0) {
			uwsgi_error("emperor_add()/bind()");
			free(n_ui);
			c_ui->ui_next = NULL;
			return;
		}

                event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->on_demand_fd);
		uwsgi_log("[uwsgi-emperor] %s -> \"on demand\" instance detected, waiting for connections on socket \"%s\" ...\n", name, socket_name);
		return;
	}
	
	if (uwsgi_emperor_vassal_start(n_ui)) {
		// clear the vassal
		free(n_ui);
		c_ui->ui_next = NULL;
	}
}
Esempio n. 3
0
struct corerouter_session *corerouter_alloc_session(struct uwsgi_corerouter *ucr, struct uwsgi_gateway_socket *ugs, int new_connection, struct sockaddr *cr_addr, socklen_t cr_addr_len) {

	struct corerouter_session *cs = uwsgi_calloc(ucr->session_size);

	struct corerouter_peer *peer = uwsgi_calloc(sizeof(struct corerouter_peer));
	// main_peer has only input buffer as output buffer is taken from backend peers
	size_t bufsize = ucr->buffer_size;
	if (!bufsize) bufsize = uwsgi.page_size;
	peer->in = uwsgi_buffer_new(bufsize);

	ucr->cr_table[new_connection] = peer;
	cs->main_peer = peer;

	peer->fd = new_connection;
	peer->session = cs;

	// map corerouter and socket
	cs->corerouter = ucr;
	cs->ugs = ugs;

	// set initial timeout (could be overridden)
	peer->current_timeout = ucr->socket_timeout;

	ucr->active_sessions++;

	// build the client address
	memcpy(&cs->client_sockaddr, cr_addr, cr_addr_len);
	switch(cr_addr->sa_family) {
		case AF_INET:
			if (inet_ntop(AF_INET, &cs->client_sockaddr.sa_in.sin_addr, cs->client_address, cr_addr_len) == NULL) {
				uwsgi_error("corerouter_alloc_session/inet_ntop()");
				memcpy(cs->client_address, "0.0.0.0", 7);
				cs->client_port[0] = '0';
				cs->client_port[1] = 0;
			}
			uwsgi_num2str2(cs->client_sockaddr.sa_in.sin_port, cs->client_port);
			break;
#ifdef AF_INET6
		case AF_INET6:
			if (inet_ntop(AF_INET6, &cs->client_sockaddr.sa_in6.sin6_addr, cs->client_address, cr_addr_len) == NULL) {
				uwsgi_error("corerouter_alloc_session/inet_ntop()");
				memcpy(cs->client_address, "0.0.0.0", 7);
				cs->client_port[0] = '0';
				cs->client_port[1] = 0;
			}
			uwsgi_num2str2(cs->client_sockaddr.sa_in6.sin6_port, cs->client_port);
			break;
#endif
		default:
			memcpy(cs->client_address, "0.0.0.0", 7);
			cs->client_port[0] = '0';
			cs->client_port[1] = 0;
			break;
	}

	// here we prepare the real session and set the hooks
	if (ucr->alloc_session(ucr, ugs, cs, cr_addr, cr_addr_len)) {
		corerouter_close_session(ucr, cs);
		cs = NULL;
	}
	else {
		// truly set the timeout
        	peer->timeout = cr_add_timeout(ucr, ucr->cr_table[new_connection]);
	}

	return cs;
}
Esempio n. 4
0
File: emperor.c Progetto: ahua/c
// this is the monitor for non-glob directories
void uwsgi_imperial_monitor_directory(struct uwsgi_emperor_scanner *ues) {
	struct uwsgi_instance *ui_current;
	struct dirent *de;
	struct stat st;

	if (chdir(ues->arg)) {
		uwsgi_error("chdir()");
		return;
	}

	DIR *dir = opendir(".");
	while ((de = readdir(dir)) != NULL) {

		if (!uwsgi_emperor_is_valid(de->d_name))
			continue;

		if (stat(de->d_name, &st))
			continue;

		if (!S_ISREG(st.st_mode))
			continue;

		ui_current = emperor_get(de->d_name);

		uid_t t_uid = st.st_uid;
		gid_t t_gid = st.st_gid;

		if (uwsgi.emperor_tyrant && uwsgi.emperor_tyrant_nofollow) {
			struct stat lst;
			if (lstat(de->d_name, &lst)) {
				uwsgi_error("[emperor-tyrant]/lstat()");
				if (ui_current) {
					uwsgi_log("!!! availability of file %s changed. stopping the instance... !!!\n", de->d_name);
					emperor_stop(ui_current);
				}
				continue;
			}
			t_uid = lst.st_uid;
			t_gid = lst.st_gid;
		}

		if (ui_current) {
			// check if uid or gid are changed, in such case, stop the instance
			if (uwsgi.emperor_tyrant) {
				if (t_uid != ui_current->uid || t_gid != ui_current->gid) {
					uwsgi_log("!!! permissions of file %s changed. stopping the instance... !!!\n", de->d_name);
					emperor_stop(ui_current);
					continue;
				}
			}
			// check if mtime is changed and the uWSGI instance must be reloaded
			if (st.st_mtime > ui_current->last_mod) {
				emperor_respawn(ui_current, st.st_mtime);
			}
		}
		else {
			char *socket_name = emperor_check_on_demand_socket(de->d_name);
			emperor_add(ues, de->d_name, st.st_mtime, NULL, 0, t_uid, t_gid, socket_name);
			if (socket_name) free(socket_name);
		}
	}
	closedir(dir);

	// now check for removed instances
	struct uwsgi_instance *c_ui = ui->ui_next;

	while (c_ui) {
		if (c_ui->scanner == ues) {
			if (c_ui->zerg) {
				char *colon = strrchr(c_ui->name, ':');
				if (!colon) {
					emperor_stop(c_ui);
				}
				else {
					char *filename = uwsgi_calloc(0xff);
					memcpy(filename, c_ui->name, colon - c_ui->name);
					if (stat(filename, &st)) {
						emperor_stop(c_ui);
					}
					free(filename);
				}
			}
			else {
                                if (stat(c_ui->name, &st)) {
                                       	emperor_stop(c_ui);
                                }
			}
		}
		c_ui = c_ui->ui_next;
	}
}
Esempio n. 5
0
/*
	extremely complex function for reading resources (files, url...)
	need a lot of refactoring...
*/
char *uwsgi_open_and_read(char *url, size_t *size, int add_zero, char *magic_table[]) {

	int fd;
	struct stat sb;
	char *buffer = NULL;
	char byte;
	ssize_t len;
	char *uri, *colon;
	char *domain;
	char *ip;
	int body = 0;
	char *magic_buf;

	// stdin ?
	if (!strcmp(url, "-")) {
		buffer = uwsgi_read_fd(0, size, add_zero);
	}
	// fd ?
	else if (!strncmp("fd://", url, 5)) {
		fd = atoi(url + 5);
		buffer = uwsgi_read_fd(fd, size, add_zero);
	}
	// exec ?
	else if (!strncmp("exec://", url, 5)) {
		int cpipe[2];
		if (pipe(cpipe)) {
			uwsgi_error("pipe()");
			exit(1);
		}
		uwsgi_run_command(url + 7, NULL, cpipe[1]);
		buffer = uwsgi_read_fd(cpipe[0], size, add_zero);
		close(cpipe[0]);
		close(cpipe[1]);
	}
	// http url ?
	else if (!strncmp("http://", url, 7)) {
		domain = url + 7;
		uri = strchr(domain, '/');
		if (!uri) {
			uwsgi_log("invalid http url\n");
			exit(1);
		}
		uri[0] = 0;
		uwsgi_log("domain: %s\n", domain);

		colon = uwsgi_get_last_char(domain, ':');

		if (colon) {
			colon[0] = 0;
		}


		ip = uwsgi_resolve_ip(domain);
		if (!ip) {
			uwsgi_log("unable to resolve address %s\n", domain);
			exit(1);
		}

		if (colon) {
			colon[0] = ':';
			ip = uwsgi_concat2(ip, colon);
		}
		else {
			ip = uwsgi_concat2(ip, ":80");
		}

		fd = uwsgi_connect(ip, 0, 0);

		if (fd < 0) {
			exit(1);
		}

		free(ip);

		uri[0] = '/';

		len = write(fd, "GET ", 4);
		len = write(fd, uri, strlen(uri));
		len = write(fd, " HTTP/1.0\r\n", 11);
		len = write(fd, "Host: ", 6);

		uri[0] = 0;
		len = write(fd, domain, strlen(domain));
		uri[0] = '/';

		len = write(fd, "\r\nUser-Agent: uWSGI on ", 23);
		len = write(fd, uwsgi.hostname, uwsgi.hostname_len);
		len = write(fd, "\r\n\r\n", 4);

		int http_status_code_ptr = 0;

		while (read(fd, &byte, 1) == 1) {
			if (byte == '\r' && body == 0) {
				body = 1;
			}
			else if (byte == '\n' && body == 1) {
				body = 2;
			}
			else if (byte == '\r' && body == 2) {
				body = 3;
			}
			else if (byte == '\n' && body == 3) {
				body = 4;
			}
			else if (body == 4) {
				*size = *size + 1;
				char *tmp = realloc(buffer, *size);
				if (!tmp) {
					uwsgi_error("uwsgi_open_and_read()/realloc()");
					exit(1);
				}
				buffer = tmp;
				buffer[*size - 1] = byte;
			}
			else {
				body = 0;
				http_status_code_ptr++;
				if (http_status_code_ptr == 10) {
					if (byte != '2') {
						uwsgi_log("Not usable HTTP response: %cxx\n", byte);
						if (uwsgi.has_emperor) {
							exit(UWSGI_EXILE_CODE);
						}
						else {
							exit(1);
						}
					}
				}
			}
		}

		close(fd);

		if (add_zero) {
			*size = *size + 1;
			char *tmp = realloc(buffer, *size);
			if (!tmp) {
				uwsgi_error("uwsgi_open_and_read()/realloc()");
				exit(1);
			}
			buffer = tmp;
			buffer[*size - 1] = 0;
		}

	}
	else if (!strncmp("emperor://", url, 10)) {
		if (uwsgi.emperor_fd_config < 0) {
			uwsgi_log("this is not a vassal instance\n");
			exit(1);
		}
		ssize_t rlen;
		*size = 0;
		struct uwsgi_header uh;
		size_t remains = 4;
		char *ptr = (char *) &uh;
		while(remains) {
			int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
			if (ret <= 0) {
				uwsgi_log("[uwsgi-vassal] error waiting for config header %s !!!\n", url);
				exit(1);
			}
			rlen = read(uwsgi.emperor_fd_config, ptr, remains);
			if (rlen <= 0) {
				uwsgi_log("[uwsgi-vassal] error reading config header from !!!\n", url);
				exit(1);
			}
			ptr+=rlen;
			remains-=rlen;
		}

		remains = uh.pktsize;
		if (!remains) {
			uwsgi_log("[uwsgi-vassal] invalid config from %s\n", url);
			exit(1);
		}

		buffer = uwsgi_calloc(remains + add_zero);
		ptr = buffer;
		while (remains) {
			int ret = uwsgi_waitfd(uwsgi.emperor_fd_config, 5);
                        if (ret <= 0) {
                                uwsgi_log("[uwsgi-vassal] error waiting for config %s !!!\n", url);
                                exit(1);
                        }
			rlen = read(uwsgi.emperor_fd_config, ptr, remains);
			if (rlen <= 0) {
                                uwsgi_log("[uwsgi-vassal] error reading config from !!!\n", url);
                                exit(1);
                        }
                        ptr+=rlen;
                        remains-=rlen;
		}

		*size = uh.pktsize + add_zero;
	}
#ifdef UWSGI_EMBED_CONFIG
	else if (url[0] == 0) {
		*size = &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG;
		if (add_zero) {
			*size += 1;
		}
		buffer = uwsgi_malloc(*size);
		memset(buffer, 0, *size);
		memcpy(buffer, &UWSGI_EMBED_CONFIG, &UWSGI_EMBED_CONFIG_END - &UWSGI_EMBED_CONFIG);
	}
#endif
	else if (!strncmp("data://", url, 7)) {
		fd = open(uwsgi.binary_path, O_RDONLY);
		if (fd < 0) {
			uwsgi_error_open(uwsgi.binary_path);
			exit(1);
		}
		int slot = atoi(url + 7);
		if (slot < 0) {
			uwsgi_log("invalid binary data slot requested\n");
			exit(1);
		}
		uwsgi_log("requesting binary data slot %d\n", slot);
		off_t fo = lseek(fd, 0, SEEK_END);
		if (fo < 0) {
			uwsgi_error("lseek()");
			uwsgi_log("invalid binary data slot requested\n");
			exit(1);
		}
		int i = 0;
		uint64_t datasize = 0;
		for (i = 0; i <= slot; i++) {
			fo = lseek(fd, -9, SEEK_CUR);
			if (fo < 0) {
				uwsgi_error("lseek()");
				uwsgi_log("invalid binary data slot requested\n");
				exit(1);
			}
			ssize_t len = read(fd, &datasize, 8);
			if (len != 8) {
				uwsgi_error("read()");
				uwsgi_log("invalid binary data slot requested\n");
				exit(1);
			}
			if (datasize == 0) {
				uwsgi_log("0 size binary data !!!\n");
				exit(1);
			}
			fo = lseek(fd, -(datasize + 9), SEEK_CUR);
			if (fo < 0) {
				uwsgi_error("lseek()");
				uwsgi_log("invalid binary data slot requested\n");
				exit(1);
			}

			if (i == slot) {
				*size = datasize;
				if (add_zero) {
					*size += 1;
				}
				buffer = uwsgi_malloc(*size);
				memset(buffer, 0, *size);
				len = read(fd, buffer, datasize);
				if (len != (ssize_t) datasize) {
					uwsgi_error("read()");
					uwsgi_log("invalid binary data slot requested\n");
					exit(1);
				}
			}
		}
	}
	else if (!strncmp("sym://", url, 6)) {
		char *symbol = uwsgi_concat3("_binary_", url + 6, "_start");
		void *sym_start_ptr = dlsym(RTLD_DEFAULT, symbol);
		if (!sym_start_ptr) {
			uwsgi_log("unable to find symbol %s\n", symbol);
			exit(1);
		}
		free(symbol);
		symbol = uwsgi_concat3("_binary_", url + 6, "_end");
		void *sym_end_ptr = dlsym(RTLD_DEFAULT, symbol);
		if (!sym_end_ptr) {
			uwsgi_log("unable to find symbol %s\n", symbol);
			exit(1);
		}
		free(symbol);

		*size = sym_end_ptr - sym_start_ptr;
		if (add_zero) {
			*size += 1;
		}
		buffer = uwsgi_malloc(*size);
		memset(buffer, 0, *size);
		memcpy(buffer, sym_start_ptr, sym_end_ptr - sym_start_ptr);

	}
#ifdef UWSGI_ELF
	else if (!strncmp("section://", url, 10)) {
		size_t s_len = 0;
		buffer = uwsgi_elf_section(uwsgi.binary_path, url + 10, &s_len);
		if (!buffer) {
			uwsgi_log("unable to find section %s in %s\n", url + 10, uwsgi.binary_path);
			exit(1);
		}
		*size = s_len;
		if (add_zero)
			*size += 1;
	}
#endif
	// fallback to file
	else {
		fd = open(url, O_RDONLY);
		if (fd < 0) {
			uwsgi_error_open(url);
			exit(1);
		}

		if (fstat(fd, &sb)) {
			uwsgi_error("fstat()");
			exit(1);
		}

		if (S_ISFIFO(sb.st_mode)) {
			buffer = uwsgi_read_fd(fd, size, add_zero);
			close(fd);
			goto end;
		}

		buffer = uwsgi_malloc(sb.st_size + add_zero);

		len = read(fd, buffer, sb.st_size);
		if (len != sb.st_size) {
			uwsgi_error("read()");
			exit(1);
		}

		close(fd);

		*size = sb.st_size + add_zero;

		if (add_zero)
			buffer[sb.st_size] = 0;
	}

end:

	if (magic_table) {

		magic_buf = magic_sub(buffer, *size, size, magic_table);
		free(buffer);
		return magic_buf;
	}

	return buffer;
}
Esempio n. 6
0
ssize_t uwsgi_redis_logger(struct uwsgi_logger *ul, char *message, size_t len) {

	ssize_t ret,ret2;
	struct uwsgi_redislog_state *uredislog = NULL;

	if (!ul->configured) {

		if (!ul->data) {
			ul->data = uwsgi_calloc(sizeof(struct uwsgi_redislog_state));
			uredislog = (struct uwsgi_redislog_state *) ul->data;
		}

		if (ul->arg != NULL) {
			char *logarg = uwsgi_str(ul->arg);
			char *comma1 = strchr(logarg, ',');
			if (!comma1) {
				uredislog->address = logarg;
				goto done;
			}
			*comma1 = 0;
			uredislog->address = logarg;
			comma1++;
			if (*comma1 == 0) goto done;

			char *comma2 = strchr(comma1,',');
			if (!comma2) {
				uredislog->command = uwsgi_redis_logger_build_command(comma1);
				goto done;
			}

			*comma2 = 0;
			uredislog->command = uwsgi_redis_logger_build_command(comma1);
			comma2++;
			if (*comma2 == 0) goto done;

			uredislog->prefix = comma2;
		}

done:

		if (!uredislog->address) uredislog->address = uwsgi_str("127.0.0.1:6379");
		if (!uredislog->command) uredislog->command = "*3\r\n$7\r\npublish\r\n$5\r\nuwsgi\r\n";
		if (!uredislog->prefix) uredislog->prefix = "";

		uredislog->fd = -1;

		uredislog->iovec[0].iov_base = uredislog->command;
		uredislog->iovec[0].iov_len = strlen(uredislog->command);
		uredislog->iovec[1].iov_base = "$";
		uredislog->iovec[1].iov_len = 1;

		uredislog->iovec[2].iov_base = uredislog->msgsize;

		uredislog->iovec[3].iov_base = "\r\n";
		uredislog->iovec[3].iov_len = 2;

		uredislog->iovec[4].iov_base = uredislog->prefix;
		uredislog->iovec[4].iov_len = strlen(uredislog->prefix);

		uredislog->iovec[6].iov_base = "\r\n";
		uredislog->iovec[6].iov_len = 2;

		ul->configured = 1;
	}

	uredislog = (struct uwsgi_redislog_state *) ul->data;
	if (uredislog->fd == -1) {
		uredislog->fd = uwsgi_connect(uredislog->address, uwsgi.socket_timeout, 0);
	}

	if (uredislog->fd == -1) return -1;

	// drop newline
        if (message[len-1] == '\n') len--;

	uwsgi_num2str2(len + uredislog->iovec[4].iov_len, uredislog->msgsize);
	uredislog->iovec[2].iov_len = strlen(uredislog->msgsize);

	uredislog->iovec[5].iov_base = message;
	uredislog->iovec[5].iov_len = len;
	
	ret = writev(uredislog->fd, uredislog->iovec, 7);
	if (ret <= 0) {
		close(uredislog->fd);
		uredislog->fd = -1;
		return -1;
	}

again:
	// read til a \n is found (ugly but fast)
	ret2 = read(uredislog->fd, uredislog->response, 8);
	if (ret2 <= 0) {
		close(uredislog->fd);
		uredislog->fd = -1;
		return -1;
	}

	if (!memchr(uredislog->response, '\n', ret2)) {
		goto again;
	}

	return ret;

}
Esempio n. 7
0
File: asyncio.c Progetto: Algy/uwsgi
static void asyncio_loop() {

	if (!uwsgi.has_threads && uwsgi.mywid == 1) {
		uwsgi_log("!!! Running asyncio without threads IS NOT recommended, enable them with --enable-threads !!!\n");
	}

	if (uwsgi.socket_timeout < 30) {
		uwsgi_log("!!! Running asyncio with a socket-timeout lower than 30 seconds is not recommended, tune it with --socket-timeout !!!\n");
	}

	if (!uwsgi.async_waiting_fd_table)
		uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
	if (!uwsgi.async_proto_fd_table)
        	uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);

	// get the GIL
	UWSGI_GET_GIL

	up.gil_get = gil_asyncio_get;
	up.gil_release = gil_asyncio_release;

	uwsgi.wait_write_hook = uwsgi_asyncio_wait_write_hook;
	uwsgi.wait_read_hook = uwsgi_asyncio_wait_read_hook;

	if (uwsgi.async < 1) {
		uwsgi_log("the asyncio loop engine requires async mode (--async <n>)\n");
		exit(1);
	}

	if (!uwsgi.schedule_to_main) {
                uwsgi_log("*** DANGER *** asyncio mode without coroutine/greenthread engine loaded !!!\n");
        }

	if (!uwsgi.schedule_to_req) {
		uwsgi.schedule_to_req = async_schedule_to_req_green;
	}
	else {
		uwsgi.schedule_fix = uwsgi_asyncio_schedule_fix;
	}

#ifndef PYTHREE
	PyObject *asyncio = PyImport_ImportModule("trollius");
#else
	PyObject *asyncio = PyImport_ImportModule("asyncio");
#endif
	if (!asyncio) uwsgi_pyexit;

	uasyncio.mod = asyncio;

	uasyncio.loop = PyObject_CallMethod(asyncio, "get_event_loop", NULL);
	if (!uasyncio.loop) uwsgi_pyexit;

	 // main greenlet waiting for connection (one greenlet per-socket)
        PyObject *asyncio_accept = PyCFunction_New(uwsgi_asyncio_accept_def, NULL);
	Py_INCREF(asyncio_accept);

	uasyncio.request = PyCFunction_New(uwsgi_asyncio_request_def, NULL);
	if (!uasyncio.request) uwsgi_pyexit;

	uasyncio.hook_fd = PyCFunction_New(uwsgi_asyncio_hook_fd_def, NULL);
	if (!uasyncio.hook_fd) uwsgi_pyexit;
	uasyncio.hook_timeout = PyCFunction_New(uwsgi_asyncio_hook_timeout_def, NULL);
	if (!uasyncio.hook_timeout) uwsgi_pyexit;
	uasyncio.hook_fix = PyCFunction_New(uwsgi_asyncio_hook_fix_def, NULL);
	if (!uasyncio.hook_fix) uwsgi_pyexit;

	Py_INCREF(uasyncio.request);
	Py_INCREF(uasyncio.hook_fd);
	Py_INCREF(uasyncio.hook_timeout);
	Py_INCREF(uasyncio.hook_fix);

	// call add_handler on each socket
	struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
	while(uwsgi_sock) {
		if (PyObject_CallMethod(uasyncio.loop, "add_reader", "iOl", uwsgi_sock->fd, asyncio_accept, (long) uwsgi_sock) == NULL) {
			uwsgi_pyexit;
		}
		uwsgi_sock = uwsgi_sock->next;
	}	

	if (PyObject_CallMethod(uasyncio.loop, "run_forever", NULL) == NULL) {
		uwsgi_pyexit;
	}

	// never here ?
}
Esempio n. 8
0
int uwsgi_python_init() {

#ifndef UWSGI_PYPY
	char *pyversion = strchr(Py_GetVersion(), '\n');
	if (!pyversion) {
        	uwsgi_log_initial("Python version: %s\n", Py_GetVersion());
	}
	else {
        	uwsgi_log_initial("Python version: %.*s %s\n", pyversion-Py_GetVersion(), Py_GetVersion(), Py_GetCompiler()+1);
	}
#else
	uwsgi_log_initial("PyPy version: %s\n", PYPY_VERSION);
#endif

	if (up.home != NULL) {
#ifdef PYTHREE
		wchar_t *wpyhome;
		size_t len = strlen(up.home) + 1; 
		wpyhome = uwsgi_calloc(sizeof(wchar_t) * len );
		if (!wpyhome) {
			uwsgi_error("malloc()");
			exit(1);
		}
		mbstowcs(wpyhome, up.home, len);
		Py_SetPythonHome(wpyhome);
		// do not free this memory !!!
		//free(wpyhome);
#else
		Py_SetPythonHome(up.home);
#endif
		uwsgi_log("Set PythonHome to %s\n", up.home);
	}


#ifdef PYTHREE
	wchar_t pname[6];
	mbstowcs(pname, "uWSGI", 6);
	Py_SetProgramName(pname);
#else
	Py_SetProgramName("uWSGI");
#endif


#ifndef UWSGI_PYPY
	Py_OptimizeFlag = up.optimize;
#endif

	Py_Initialize();

	if (!uwsgi.has_threads) {
		uwsgi_log("*** Python threads support is disabled. You can enable it with --enable-threads ***\n");
	}

	up.wsgi_spitout = PyCFunction_New(uwsgi_spit_method, NULL);
	up.wsgi_writeout = PyCFunction_New(uwsgi_write_method, NULL);

	up.main_thread = PyThreadState_Get();

        // by default set a fake GIL (little impact on performance)
        up.gil_get = gil_fake_get;
        up.gil_release = gil_fake_release;

        up.swap_ts = simple_swap_ts;
        up.reset_ts = simple_reset_ts;
	

	uwsgi_log_initial("Python main interpreter initialized at %p\n", up.main_thread);

	return 1;

}
Esempio n. 9
0
File: xslt.c Progetto: AGoodId/uwsgi
static char *uwsgi_xslt_apply(char *xmlfile, char *xsltfile, char *params, int *rlen) {

	char **vparams = NULL;
	char *tmp_params = NULL;
	uint16_t count = 0;
	if (params) {
		// first count the number of items
		size_t i;
		size_t params_len = strlen(params);
		for(i=0;i<params_len;i++) {
			if (params[i] == '=') {
				count++;
			}
		}
		vparams = uwsgi_calloc( sizeof(char *) * ((count * 2) + 1));
		tmp_params = uwsgi_str(params);
		char *p = strtok(tmp_params, "&");
		int pos = 0;
		while(p) {
			char *equal = strchr(p, '=');
			if (equal) {
				*equal = 0;
				vparams[pos] = p; pos++;
				vparams[pos] = uwsgi_concat3("\"", equal+1, "\""); pos++;	
			}
			p = strtok(NULL, "&");
		}
	}

	// we reset them every time to avoid collision with other xml engines
	xmlSubstituteEntitiesDefault(1);
	xmlLoadExtDtdDefaultValue = 1;

        xmlDocPtr doc = xmlParseFile(xmlfile);
        if (!doc) {
		if (vparams) {
			int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
			free(tmp_params);
			free(vparams);
		}
		return NULL;
	}

        xsltStylesheetPtr ss = xsltParseStylesheetFile((const xmlChar *) xsltfile);
        if (!ss) {
		xmlFreeDoc(doc);
		if (vparams) {
			int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
			free(tmp_params);
			free(vparams);
		}
                return NULL;
        }

        xmlDocPtr res = xsltApplyStylesheet(ss, doc, (const char **) vparams);
	if (!res) {
		xsltFreeStylesheet(ss);
		xmlFreeDoc(doc);
		if (vparams) {
			int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
			free(tmp_params);
			free(vparams);
		}
		return NULL;
	}

        xmlChar *output;
        int ret = xsltSaveResultToString(&output, rlen, res, ss);
	xsltFreeStylesheet(ss);
	xmlFreeDoc(res);
	xmlFreeDoc(doc);
	if (vparams) {
		int i; for(i=1;i<(count*2);i+=2) free(vparams[i]);
		free(tmp_params);
		free(vparams);
	}
	if (ret < 0) return NULL;
	return (char *) output;
}
Esempio n. 10
0
void uwsgi_fork_server(char *socket) {
	// map fd 0 to /dev/null to avoid mess
	uwsgi_remap_fd(0, "/dev/null");

	int fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
	if (fd < 0) exit(1);

	// automatically receive credentials (TODO make something useful with them, like checking the pid is from the Emperor)
	if (uwsgi_socket_passcred(fd)) exit(1);

	// initialize the event queue
	int eq = event_queue_init();
	if (uwsgi.has_emperor) {
		event_queue_add_fd_read(eq, uwsgi.emperor_fd);
	}
	event_queue_add_fd_read(eq, fd);

	// now start waiting for connections
	for(;;) {
		int interesting_fd = -1;
		int rlen = event_queue_wait(eq, -1, &interesting_fd);
		if (rlen <= 0) continue;
		if (uwsgi.has_emperor && interesting_fd == uwsgi.emperor_fd) {
			char byte;
        		ssize_t rlen = read(uwsgi.emperor_fd, &byte, 1);
        		if (rlen > 0) {
                		uwsgi_log_verbose("received message %d from emperor\n", byte);
			}
			exit(0);
		}
		if (interesting_fd != fd) continue;
		struct sockaddr_un client_src;
        	socklen_t client_src_len = 0;
        	int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
        	if (client_fd < 0) {
                	uwsgi_error("uwsgi_fork_server()/accept()");
			continue;
        	}
		char hbuf[4];
		pid_t ppid = -1;
		uid_t uid = -1;
		gid_t gid = -1;
		int fds_count = 8;
		size_t remains = 4;
		// we can receive up to 8 fds (generally from 1 to 3)
		int fds[8];
		// we only read 4 bytes header
		ssize_t len = uwsgi_recv_cred_and_fds(client_fd, hbuf, remains, &ppid, &uid, &gid, fds, &fds_count);
		uwsgi_log_verbose("[uwsgi-fork-server] connection from pid: %d uid: %d gid:%d fds:%d\n", ppid, uid, gid, fds_count);
		if (len <= 0 || fds_count < 1) {
			uwsgi_error("uwsgi_fork_server()/recvmsg()");
			goto end;
		}
		remains -= len;
	
		if (uwsgi_read_nb(client_fd, hbuf + (4-remains), remains, uwsgi.socket_timeout)) {
			uwsgi_error("uwsgi_fork_server()/uwsgi_read_nb()");
			goto end;
		}

		struct uwsgi_header *uh = (struct uwsgi_header *) hbuf;
		// this memory area must be freed in the right place !!!
		char *body_argv = uwsgi_malloc(uh->_pktsize);
		if (uwsgi_read_nb(client_fd, body_argv, uh->_pktsize, uwsgi.socket_timeout)) {
			free(body_argv);
                        uwsgi_error("uwsgi_fork_server()/uwsgi_read_nb()");
                        goto end;
                }

		pid_t pid = fork();
		if (pid < 0) {
			free(body_argv);
			int i;
			for(i=0;i<fds_count;i++) close(fds[i]);
			// error on fork()
			uwsgi_error("uwsgi_fork_server()/fork()");
			goto end;		
		}
		else if (pid > 0) {
			free(body_argv);
			// close inherited decriptors 
			int i;
			for(i=0;i<fds_count;i++) close(fds[i]);
			// wait for child death...
			waitpid(pid, NULL, 0);
			goto end;
		}
		else {
			// close Emperor channels
			// we do not close others file desctiptor as lot
			// of funny tricks could be accomplished with them
			if (uwsgi.has_emperor) {
				close(uwsgi.emperor_fd);
				if (uwsgi.emperor_fd_config > -1) close(uwsgi.emperor_fd_config);
			}
			
			// set EMPEROR_FD and FD_CONFIG env vars	
			char *uef = uwsgi_num2str(fds[0]);
        		if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
                		uwsgi_error("uwsgi_fork_server()/setenv()");
                		exit(1);
        		}
        		free(uef);

			int pipe_config = -1;
			int on_demand = -1;

			if (uh->modifier2 & VASSAL_HAS_CONFIG && fds_count > 1) {
				pipe_config = fds[1];	
				char *uef = uwsgi_num2str(pipe_config);
				if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
                                	uwsgi_error("uwsgi_fork_server()/setenv()");
                                	exit(1);
                        	}
                        	free(uef);
			}

			if (uh->modifier2 & VASSAL_HAS_ON_DEMAND && fds_count > 1) {
				if (pipe_config > -1) {
					if (fds_count > 2) {
						on_demand = fds[2];
					}
				}
				else {
					on_demand = fds[1];
				}
			}
			// dup the on_demand socket to 0 and close it
			if (on_demand > -1) {
				if (dup2(on_demand, 0) < 0) {
					uwsgi_error("uwsgi_fork_server()/dup2()");
					exit(1);
				}
				close(on_demand);
			}

			// now fork again and die
			pid_t new_pid = fork();
			if (new_pid < 0) {
                        	uwsgi_error("uwsgi_fork_server()/fork()");
				exit(1);
			}
			else if (new_pid > 0) {
				exit(0);
			}
			else {
				// send the pid to the client_fd and close it
				struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
				// leave space for header
				ub->pos = 4;
				if (uwsgi_buffer_append_keynum(ub, "pid", 3, getpid())) exit(1); 
				// fix uwsgi header
        			if (uwsgi_buffer_set_uh(ub, 35, 0)) goto end;
				// send_pid()
				if (uwsgi_write_nb(client_fd, ub->buf, ub->pos, uwsgi.socket_timeout)) exit(1);
				close(client_fd);
				uwsgi_log("double fork() and reparenting successful (new pid: %d)\n", getpid());
				uwsgi_buffer_destroy(ub);


				// now parse the uwsgi packet array and build the argv
				struct uwsgi_string_list *usl = NULL, *usl_argv = NULL;
				uwsgi_hooked_parse_array(body_argv, uh->_pktsize, parse_argv_hook, &usl_argv);
				free(body_argv);

				// build new argc/argv
				uwsgi.new_argc = 0;
				size_t procname_len = 1;
				uwsgi_foreach(usl, usl_argv) {
					uwsgi.new_argc++;
					procname_len += usl->len + 1;
				}

				char *new_procname = uwsgi_calloc(procname_len);
				
				uwsgi.new_argv = uwsgi_calloc(sizeof(char *) * (uwsgi.new_argc + 1));
				int counter = 0;
				uwsgi_foreach(usl, usl_argv) {
					uwsgi.new_argv[counter] = usl->value;
					strcat(new_procname, usl->value);
					strcat(new_procname, " ");
					counter++;
				}
				// fix process name
				uwsgi_set_processname(new_procname);
				free(new_procname);
				// this is the only step required to have a consistent environment
				uwsgi.fork_socket = NULL;
				// this avoids the process to re-exec itself
				uwsgi.exit_on_reload = 1;
				// fixup the Emperor communication
				uwsgi_check_emperor();
				// continue with uWSGI startup
				return;
			}
		}	
Esempio n. 11
0
static void tornado_loop() {

	if (!uwsgi.has_threads && uwsgi.mywid == 1) {
		uwsgi_log("!!! Running tornado without threads IS NOT recommended, enable them with --enable-threads !!!\n");
	}

	if (uwsgi.socket_timeout < 30) {
		uwsgi_log("!!! Running tornado with a socket-timeout lower than 30 seconds is not recommended, tune it with --socket-timeout !!!\n");
	}

	if (!uwsgi.async_waiting_fd_table)
                uwsgi.async_waiting_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);
        if (!uwsgi.async_proto_fd_table)
                uwsgi.async_proto_fd_table = uwsgi_calloc(sizeof(struct wsgi_request *) * uwsgi.max_fd);

	// get the GIL
	UWSGI_GET_GIL

	up.gil_get = gil_tornado_get;
	up.gil_release = gil_tornado_release;

	uwsgi.wait_write_hook = uwsgi_tornado_wait_write_hook;
	uwsgi.wait_read_hook = uwsgi_tornado_wait_read_hook;

	uwsgi.schedule_fix = uwsgi_tornado_schedule_fix;

	if (uwsgi.async < 2) {
		uwsgi_log("the tornado loop engine requires async mode (--async <n>)\n");
		exit(1);
	}

	if (!uwsgi.schedule_to_main) {
                uwsgi_log("*** DANGER *** tornado mode without coroutine/greenthread engine loaded !!!\n");
        }

	PyObject *tornado_dict = get_uwsgi_pydict("tornado.ioloop");
	if (!tornado_dict) uwsgi_pyexit;

	PyObject *tornado_IOLoop = PyDict_GetItemString(tornado_dict, "IOLoop");
	if (!tornado_IOLoop) uwsgi_pyexit;

	utornado.ioloop = PyObject_CallMethod(tornado_IOLoop, "instance", NULL);
	if (!utornado.ioloop) uwsgi_pyexit;


	 // main greenlet waiting for connection (one greenlet per-socket)
        PyObject *uwsgi_tornado_accept = PyCFunction_New(uwsgi_tornado_accept_def, NULL);
	Py_INCREF(uwsgi_tornado_accept);

	utornado.request = PyCFunction_New(uwsgi_tornado_request_def, NULL);
	if (!utornado.request) uwsgi_pyexit;
	utornado.hook_fd = PyCFunction_New(uwsgi_tornado_hook_fd_def, NULL);
	if (!utornado.hook_fd) uwsgi_pyexit;
	utornado.hook_timeout = PyCFunction_New(uwsgi_tornado_hook_timeout_def, NULL);
	if (!utornado.hook_timeout) uwsgi_pyexit;
	utornado.hook_fix = PyCFunction_New(uwsgi_tornado_hook_fix_def, NULL);
	if (!utornado.hook_fix) uwsgi_pyexit;

	utornado.read = PyObject_GetAttrString(utornado.ioloop, "READ");
	if (!utornado.read) uwsgi_pyexit;
	utornado.write = PyObject_GetAttrString(utornado.ioloop, "WRITE");
	if (!utornado.write) uwsgi_pyexit;

	utornado.functools = PyImport_ImportModule("functools"); 
	if (!utornado.functools)  uwsgi_pyexit;
	
	Py_INCREF(utornado.request);
	Py_INCREF(utornado.hook_fd);
	Py_INCREF(utornado.hook_timeout);
	Py_INCREF(utornado.hook_fix);
	Py_INCREF(utornado.read);
	Py_INCREF(utornado.write);

	// call add_handler on each socket
	struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
	while(uwsgi_sock) {
		if (PyObject_CallMethod(utornado.ioloop, "add_handler", "iOO", uwsgi_sock->fd, uwsgi_tornado_accept, utornado.read) == NULL) {
			uwsgi_pyexit;
		}
		uwsgi_sock = uwsgi_sock->next;
	}	

	if (PyObject_CallMethod(utornado.ioloop, "start", NULL) == NULL) {
		uwsgi_pyexit;
	}

	// never here ?
}
Esempio n. 12
0
static void stats_pusher_statsd(struct uwsgi_stats_pusher_instance *uspi, time_t now, char *json, size_t json_len) {

	if (!uspi->configured) {
		struct statsd_node *sn = uwsgi_calloc(sizeof(struct statsd_node));
		char *comma = strchr(uspi->arg, ',');
		if (comma) {
			sn->prefix = comma+1;
			sn->prefix_len = strlen(sn->prefix);
			*comma = 0;
		}
		else {
			sn->prefix = "uwsgi";
			sn->prefix_len = 5;
		}

		char *colon = strchr(uspi->arg, ':');
		if (!colon) {
			uwsgi_log("invalid statsd address %s\n", uspi->arg);
			if (comma) *comma = ',';
			free(sn);
			return;
		}
		sn->addr_len = socket_to_in_addr(uspi->arg, colon, 0, &sn->addr.sa_in);

		sn->fd = socket(AF_INET, SOCK_DGRAM, 0);
		if (sn->fd < 0) {
			uwsgi_error("stats_pusher_statsd()/socket()");
			if (comma) *comma = ',';
                        free(sn);
                        return;
		}
		uwsgi_socket_nb(sn->fd);
		if (comma) *comma = ',';
		uspi->data = sn;
		uspi->configured = 1;
	}

	// we use the same buffer for all of the packets
	struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
	struct uwsgi_metric *um = uwsgi.metrics;
	while(um) {
		if (u_stats_pusher_statsd.no_workers && !uwsgi_starts_with(um->name, um->name_len, "worker.", 7)) {
		    goto next;
		}
		uwsgi_rlock(uwsgi.metrics_lock);
		// ignore return value
		if (um->type == UWSGI_METRIC_GAUGE) {
			statsd_send_metric(ub, uspi, um->name, um->name_len, *um->value, "|g");
		}
		else {
			statsd_send_metric(ub, uspi, um->name, um->name_len, *um->value, "|c");
		}
		uwsgi_rwunlock(uwsgi.metrics_lock);
		if (um->reset_after_push){
			uwsgi_wlock(uwsgi.metrics_lock);
			*um->value = um->initial_value;
			uwsgi_rwunlock(uwsgi.metrics_lock);
		}
		next:
		um = um->next;
	}
	uwsgi_buffer_destroy(ub);
}
Esempio n. 13
0
int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, PerlInterpreter **interpreters) {

	struct stat st;
	int i;
	SV **callables;

	time_t now = uwsgi_now();

	char *app_name = uwsgi_concat2n(app, app_len, "", 0);

	// prepare for $0
	uperl.embedding[1] = app_name;
		
	int fd = open(app_name, O_RDONLY);
	if (fd < 0) {
		uwsgi_error_open(app_name);
		goto clear2;
	}

	if (fstat(fd, &st)) {
		uwsgi_error("fstat()");
		close(fd);
		goto clear2;
	}

	char *buf = uwsgi_calloc(st.st_size+1);
	if (read(fd, buf, st.st_size) != st.st_size) {
		uwsgi_error("read()");
		close(fd);
		free(buf);
		goto clear2;
	}

	close(fd);

	// the first (default) app, should always be loaded in the main interpreter
	if (interpreters == NULL) {
		if (uwsgi_apps_cnt) {
			interpreters = uwsgi_calloc(sizeof(PerlInterpreter *) * uwsgi.threads);
			interpreters[0] = uwsgi_perl_new_interpreter();
			if (!interpreters[0]) {
				uwsgi_log("unable to create new perl interpreter\n");
				free(interpreters);
				goto clear2;
			}
		}
		else {
			interpreters = uperl.main;
		}		
	}

	if (!interpreters) {
		goto clear2;
	}


	callables = uwsgi_calloc(sizeof(SV *) * uwsgi.threads);
	uperl.tmp_streaming_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
	uperl.tmp_input_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
	uperl.tmp_error_stash = uwsgi_calloc(sizeof(HV *) * uwsgi.threads);
	uperl.tmp_stream_responder = uwsgi_calloc(sizeof(CV *) * uwsgi.threads);
	uperl.tmp_psgix_logger = uwsgi_calloc(sizeof(CV *) * uwsgi.threads);

	for(i=0;i<uwsgi.threads;i++) {

		if (i > 0 && interpreters != uperl.main) {
		
			interpreters[i] = uwsgi_perl_new_interpreter();
			if (!interpreters[i]) {
				uwsgi_log("unable to create new perl interpreter\n");
				// what to do here ? i hope no-one will use threads with dynamic apps...but clear the whole stuff...
				free(callables);
				uwsgi_perl_free_stashes();
				while(i>=0) {
					perl_destruct(interpreters[i]);	
					perl_free(interpreters[i]);
					goto clear2;
				}
			}
		}

		PERL_SET_CONTEXT(interpreters[i]);

		uperl.tmp_current_i = i;


		if (uperl.locallib) {
                        uwsgi_log("using %s as local::lib directory\n", uperl.locallib);
                        uperl.embedding[1] = uwsgi_concat2("-Mlocal::lib=", uperl.locallib);
                        uperl.embedding[2] = app_name;
                        if (perl_parse(interpreters[i], xs_init, 3, uperl.embedding, NULL)) {
				// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
				free(uperl.embedding[1]);
				uperl.embedding[1] = app_name;
				free(callables);
				uwsgi_perl_free_stashes();
				goto clear;
                        }
			free(uperl.embedding[1]);
			uperl.embedding[1] = app_name;
                }
		else {
			if (perl_parse(interpreters[i], xs_init, 2, uperl.embedding, NULL)) {
				// what to do here ? i hope no-one will use threads with dynamic apps... but clear the whole stuff...
				free(callables);
				uwsgi_perl_free_stashes();
				goto clear;
        		}
		}

		perl_eval_pv("use IO::Handle;", 0);
		perl_eval_pv("use IO::File;", 0);
		perl_eval_pv("use Scalar::Util;", 0);
		if (!uperl.no_die_catch) {
			perl_eval_pv("use Devel::StackTrace;", 0);
			if (!SvTRUE(ERRSV)) {
				uperl.stacktrace_available = 1;
				perl_eval_pv("$SIG{__DIE__} = \\&uwsgi::stacktrace;", 0);
			}
		}

		if (uperl.argv_items || uperl.argv_item) {
			AV *uperl_argv = GvAV(PL_argvgv);
			if (uperl.argv_items) {
				char *argv_list = uwsgi_str(uperl.argv_items);
				char *p = strtok(argv_list, " ");
				while(p) {
					av_push(uperl_argv, newSVpv(p, 0));
					p = strtok(NULL, " ");
				}
			}
			struct uwsgi_string_list *usl = uperl.argv_item;
			while(usl) {
				av_push(uperl_argv, newSVpv(usl->value, usl->len));
				usl = usl->next;
			}
		}
		

		SV *dollar_zero = get_sv("0", GV_ADD);
		sv_setsv(dollar_zero, newSVpv(app, app_len));

		callables[i] = perl_eval_pv(uwsgi_concat4("#line 1 ", app_name, "\n", buf), 0);
		if (!callables[i]) {
			uwsgi_log("unable to find PSGI function entry point.\n");
			// what to do here ? i hope no-one will use threads with dynamic apps...
			free(callables);
			uwsgi_perl_free_stashes();
                	goto clear;
		}

		PERL_SET_CONTEXT(interpreters[0]);
	}

	free(buf);

	if(SvTRUE(ERRSV)) {
        	uwsgi_log("%s\n", SvPV_nolen(ERRSV));
		free(callables);
		uwsgi_perl_free_stashes();
		goto clear;
        }

	if (uwsgi_apps_cnt >= uwsgi.max_apps) {
		uwsgi_log("ERROR: you cannot load more than %d apps in a worker\n", uwsgi.max_apps);
		goto clear;
	}

	int id = uwsgi_apps_cnt;
	struct uwsgi_app *wi = NULL;

	if (wsgi_req) {
		// we need a copy of app_id
		wi = uwsgi_add_app(id, psgi_plugin.modifier1, uwsgi_concat2n(wsgi_req->appid, wsgi_req->appid_len, "", 0), wsgi_req->appid_len, interpreters, callables);
	}
	else {
		wi = uwsgi_add_app(id, psgi_plugin.modifier1, "", 0, interpreters, callables);
	}

	wi->started_at = now;
	wi->startup_time = uwsgi_now() - now;

        uwsgi_log("PSGI app %d (%s) loaded in %d seconds at %p (interpreter %p)\n", id, app_name, (int) wi->startup_time, callables[0], interpreters[0]);
	free(app_name);

	// copy global data to app-specific areas
	wi->stream = uperl.tmp_streaming_stash;
	wi->input = uperl.tmp_input_stash;
	wi->error = uperl.tmp_error_stash;
	wi->responder0 = uperl.tmp_stream_responder;
	wi->responder1 = uperl.tmp_psgix_logger;

	uwsgi_emulate_cow_for_apps(id);


	// restore context if required
	if (interpreters != uperl.main) {
		PERL_SET_CONTEXT(uperl.main[0]);
	}

	uperl.loaded = 1;

	return id;

clear:
	if (interpreters != uperl.main) {
		for(i=0;i<uwsgi.threads;i++) {
			perl_destruct(interpreters[i]);
			perl_free(interpreters[i]);
		}
		free(interpreters);
	}

	PERL_SET_CONTEXT(uperl.main[0]);
clear2:
	free(app_name);
       	return -1; 
}
Esempio n. 14
0
void uwsgi_detach_daemons() {
	struct uwsgi_daemon *ud = uwsgi.daemons;
	while (ud) {
#ifdef UWSGI_SSL
		// stop any legion daemon, doesn't matter if dumb or smart
		if (ud->pid > 0 && (ud->legion || !ud->pidfile)) {
#else
		// stop only dumb 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 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;
			while (!kill(ud->pid, 0)) {
				kill(-ud->pid, ud->stop_signal);
				sleep(1);
				waitpid(-ud->pid, &waitpid_status, WNOHANG);
				if (uwsgi_now() >= timeout) {
					uwsgi_log("[uwsgi-daemons] daemon did not die in time, killing (pid: %d): %s\n", (int) ud->pid, ud->command);
					kill(-ud->pid, SIGKILL);
					break;
				}
			}
			// unregister daemon to prevent it from being respawned
			ud->registered = 0;
		}
		ud = ud->next;
	}
}


void uwsgi_spawn_daemon(struct uwsgi_daemon *ud) {

	// skip unregistered daemons
	if (!ud->registered) return;

	int throttle = 0;

	if (uwsgi.current_time - ud->last_spawn <= 3) {
		throttle = ud->respawns - (uwsgi.current_time - ud->last_spawn);
		// if ud->respawns == 0 then we can end up with throttle < 0
		if (throttle <= 0) throttle = 1;
	}

	pid_t pid = uwsgi_fork("uWSGI external daemon");
	if (pid < 0) {
		uwsgi_error("fork()");
		return;
	}

	if (pid > 0) {
		ud->has_daemonized = 0;
		ud->pid = pid;
		ud->status = 1;
		ud->pidfile_checks = 0;
		if (ud->respawns == 0) {
			ud->born = uwsgi_now();
		}

		ud->respawns++;
		ud->last_spawn = uwsgi_now();

	}
	else {
		// close uwsgi sockets
		uwsgi_close_all_sockets();
		uwsgi_close_all_fds();

		if (ud->gid) {
			if (setgid(ud->gid)) {
				uwsgi_error("uwsgi_spawn_daemon()/setgid()");
				exit(1);
			}
		}

		if (ud->uid) {
			if (setuid(ud->uid)) {
				uwsgi_error("uwsgi_spawn_daemon()/setuid()");
				exit(1);
			}
		}

		if (ud->daemonize) {
			/* refork... */
			pid = fork();
			if (pid < 0) {
				uwsgi_error("fork()");
				exit(1);
			}
			if (pid != 0) {
				_exit(0);
			}
			uwsgi_write_pidfile(ud->pidfile);
		}

		if (!uwsgi.daemons_honour_stdin && !ud->honour_stdin) {
			// /dev/null will became stdin
			uwsgi_remap_fd(0, "/dev/null");
		}

		if (setsid() < 0) {
			uwsgi_error("setsid()");
			exit(1);
		}

		if (!ud->pidfile) {
#ifdef __linux__
			if (prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0)) {
				uwsgi_error("prctl()");
			}
#endif
		}


		if (throttle) {
			uwsgi_log("[uwsgi-daemons] throttling \"%s\" for %d seconds\n", ud->command, throttle);
			sleep((unsigned int) throttle);
		}

		uwsgi_log("[uwsgi-daemons] %sspawning \"%s\" (uid: %d gid: %d)\n", ud->respawns > 0 ? "re" : "", ud->command, (int) getuid(), (int) getgid());
		uwsgi_exec_command_with_args(ud->command);
		uwsgi_log("[uwsgi-daemons] unable to spawn \"%s\"\n", ud->command);

		// never here;
		exit(1);
	}

	return;
}


void uwsgi_opt_add_daemon(char *opt, char *value, void *none) {

	struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;
	char *pidfile = NULL;
	int daemonize = 0;
	int freq = 10;
	char *space = NULL;
	int stop_signal = SIGTERM;
	int reload_signal = 0;

	char *command = uwsgi_str(value);

#ifdef UWSGI_SSL
	char *legion = NULL;
	if (!uwsgi_starts_with(opt, strlen(command), "legion-", 7)) {
		space = strchr(command, ' ');
		if (!space) {
			uwsgi_log("invalid legion daemon syntax: %s\n", command);
			exit(1);
		}
		*space = 0;
		legion = command;
		command = space+1;
	}
#endif

	if (!strcmp(opt, "smart-attach-daemon") || !strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon") || !strcmp(opt, "legion-smart-attach-daemon2")) {
		space = strchr(command, ' ');
		if (!space) {
			uwsgi_log("invalid smart-attach-daemon syntax: %s\n", command);
			exit(1);
		}
		*space = 0;
		pidfile = command;
		// check for freq
		char *comma = strchr(pidfile, ',');
		if (comma) {
			*comma = 0;
			freq = atoi(comma + 1);
		}
		command = space + 1;
		if (!strcmp(opt, "smart-attach-daemon2") || !strcmp(opt, "legion-smart-attach-daemon2")) {
			daemonize = 1;
		}
	}

	if (!uwsgi_ud) {
		uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
		uwsgi_ud = uwsgi.daemons;
	}
	else {
		while (uwsgi_ud) {
			old_ud = uwsgi_ud;
			uwsgi_ud = uwsgi_ud->next;
		}

		uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
		old_ud->next = uwsgi_ud;
	}

	uwsgi_ud->command = command;
	uwsgi_ud->pid = 0;
	uwsgi_ud->status = 0;
	uwsgi_ud->freq = freq;
	uwsgi_ud->registered = 0;
	uwsgi_ud->next = NULL;
	uwsgi_ud->respawns = 0;
	uwsgi_ud->last_spawn = 0;
	uwsgi_ud->daemonize = daemonize;
	uwsgi_ud->pidfile = pidfile;
	uwsgi_ud->control = 0;
	uwsgi_ud->stop_signal = stop_signal;
	uwsgi_ud->reload_signal = reload_signal;
	if (!strcmp(opt, "attach-control-daemon")) {
		uwsgi_ud->control = 1;
	}
#ifdef UWSGI_SSL
	uwsgi_ud->legion = legion;
#endif

	uwsgi.daemons_cnt++;

}

void uwsgi_opt_add_daemon2(char *opt, char *value, void *none) {

        struct uwsgi_daemon *uwsgi_ud = uwsgi.daemons, *old_ud;

	char *d_command = NULL;
	char *d_freq = NULL;
	char *d_pidfile = NULL;
	char *d_control = NULL;
	char *d_legion = NULL;
	char *d_daemonize = NULL;
	char *d_touch = NULL;
	char *d_stopsignal = NULL;
	char *d_reloadsignal = NULL;
	char *d_stdin = NULL;
	char *d_uid = NULL;
	char *d_gid = NULL;

	char *arg = uwsgi_str(value);

	if (uwsgi_kvlist_parse(arg, strlen(arg), ',', '=',
		"command", &d_command,	
		"cmd", &d_command,	
		"exec", &d_command,	
		"freq", &d_freq,	
		"pidfile", &d_pidfile,	
		"control", &d_control,	
		"daemonize", &d_daemonize,	
		"daemon", &d_daemonize,	
		"touch", &d_touch,	
		"stopsignal", &d_stopsignal,	
		"stop_signal", &d_stopsignal,	
		"reloadsignal", &d_reloadsignal,	
		"reload_signal", &d_reloadsignal,	
		"stdin", &d_stdin,	
		"uid", &d_uid,	
		"gid", &d_gid,	
	NULL)) {
		uwsgi_log("invalid --%s keyval syntax\n", opt);
		exit(1);
	}

	if (!d_command) {
		uwsgi_log("--%s: you need to specify a 'command' key\n", opt);
		exit(1);
	}

#ifndef UWSGI_SSL
	if (d_legion) {
		uwsgi_log("legion subsystem is not supported on this uWSGI version, rebuild with ssl support\n");
		exit(1);
	}
#endif



        if (!uwsgi_ud) {
                uwsgi.daemons = uwsgi_calloc(sizeof(struct uwsgi_daemon));
                uwsgi_ud = uwsgi.daemons;
        }
        else {
                while (uwsgi_ud) {
                        old_ud = uwsgi_ud;
                        uwsgi_ud = uwsgi_ud->next;
                }

                uwsgi_ud = uwsgi_calloc(sizeof(struct uwsgi_daemon));
                old_ud->next = uwsgi_ud;
        }
        uwsgi_ud->command = d_command;
        uwsgi_ud->freq = d_freq ? atoi(d_freq) : 10;
        uwsgi_ud->daemonize = d_daemonize ? 1 : 0;
        uwsgi_ud->pidfile = d_pidfile;
        uwsgi_ud->stop_signal = d_stopsignal ? atoi(d_stopsignal) : SIGTERM;
        uwsgi_ud->reload_signal = d_reloadsignal ? atoi(d_reloadsignal) : 0;
        uwsgi_ud->control = d_control ? 1 : 0;
	uwsgi_ud->uid = d_uid ? atoi(d_uid) : 0;
	uwsgi_ud->gid = d_gid ? atoi(d_gid) : 0;
	uwsgi_ud->honour_stdin = d_stdin ? 1 : 0;
#ifdef UWSGI_SSL
        uwsgi_ud->legion = d_legion;
#endif

	if (d_touch) {
		size_t i,rlen = 0;
		char **argv = uwsgi_split_quoted(d_touch, strlen(d_touch), ";", &rlen);
		for(i=0;i<rlen;i++) {	
			uwsgi_string_new_list(&uwsgi_ud->touch, argv[i]);
		}
		if (argv) free(argv);
	}

        uwsgi.daemons_cnt++;

	free(arg);

}
Esempio n. 15
0
int bind_to_unix_dgram(char *socket_name) {

	int serverfd;
	struct sockaddr_un *uws_addr;
	socklen_t len;

	serverfd = socket(AF_UNIX, SOCK_DGRAM, 0);
	if (serverfd < 0) {
		uwsgi_error("socket()");
		uwsgi_nuclear_blast();
	}

	if (unlink(socket_name) != 0 && errno != ENOENT) {
		uwsgi_error("unlink()");
	}

	uws_addr = uwsgi_calloc(sizeof(struct sockaddr_un));
	uws_addr->sun_family = AF_UNIX;

	memcpy(uws_addr->sun_path, socket_name, UMIN(strlen(socket_name), 102));
	len = strlen(socket_name);

#ifdef __HAIKU__
	if (bind(serverfd, (struct sockaddr *) uws_addr, sizeof(struct sockaddr_un))) {
#else
	if (bind(serverfd, (struct sockaddr *) uws_addr, len + ((void *) uws_addr->sun_path - (void *) uws_addr)) != 0) {
#endif
		uwsgi_error("bind()");
		uwsgi_nuclear_blast();
	}

	return serverfd;
}

int bind_to_unix(char *socket_name, int listen_queue, int chmod_socket, int abstract_socket) {

	int serverfd;
	struct sockaddr_un *uws_addr;
	socklen_t len;

	// leave 1 byte for abstract namespace (108 linux -> 104 bsd/mac)
	if (strlen(socket_name) > 102) {
		uwsgi_log("invalid socket name\n");
		uwsgi_nuclear_blast();
	}

	if (socket_name[0] == '@') {
		abstract_socket = 1;
	}
	else if (strlen(socket_name) > 1 && socket_name[0] == '\\' && socket_name[1] == '0') {
		abstract_socket = 1;
	}

	uws_addr = malloc(sizeof(struct sockaddr_un));
	if (uws_addr == NULL) {
		uwsgi_error("malloc()");
		uwsgi_nuclear_blast();
	}

	memset(uws_addr, 0, sizeof(struct sockaddr_un));
	serverfd = socket(AF_UNIX, SOCK_STREAM, 0);
	if (serverfd < 0) {
		uwsgi_error("socket()");
		uwsgi_nuclear_blast();
	}
	if (abstract_socket == 0) {
		if (unlink(socket_name) != 0 && errno != ENOENT) {
			uwsgi_error("unlink()");
		}
	}

	if (abstract_socket == 1) {
		uwsgi_log("setting abstract socket mode (warning: only Linux supports this)\n");
	}

	uws_addr->sun_family = AF_UNIX;
	if (socket_name[0] == '@') {
		memcpy(uws_addr->sun_path + abstract_socket, socket_name + 1, UMIN(strlen(socket_name + 1), 101));
		len = strlen(socket_name) + 1;
	}
	else if (strlen(socket_name) > 1 && socket_name[0] == '\\' && socket_name[1] == '0') {
		memcpy(uws_addr->sun_path + abstract_socket, socket_name + 2, UMIN(strlen(socket_name + 2), 101));
		len = strlen(socket_name + 1) + 1;

	}
	else if (abstract_socket) {
		memcpy(uws_addr->sun_path + 1, socket_name, UMIN(strlen(socket_name), 101));
		len = strlen(socket_name) + 1;
	}
	else {
		memcpy(uws_addr->sun_path + abstract_socket, socket_name, UMIN(strlen(socket_name), 102));
		len = strlen(socket_name);
	}

#ifdef __HAIKU__
	if (bind(serverfd, (struct sockaddr *) uws_addr, sizeof(struct sockaddr_un))) {
#else
	if (bind(serverfd, (struct sockaddr *) uws_addr, len + ((void *) uws_addr->sun_path - (void *) uws_addr)) != 0) {
#endif
		uwsgi_error("bind()");
		uwsgi_nuclear_blast();
	}


	if (listen(serverfd, listen_queue) != 0) {
		uwsgi_error("listen()");
		uwsgi_nuclear_blast();
	}

	// chmod unix socket for lazy users
	if (chmod_socket == 1 && abstract_socket == 0) {
		if (uwsgi.chmod_socket_value) {
			if (chmod(socket_name, uwsgi.chmod_socket_value) != 0) {
				uwsgi_error("chmod()");
			}
		}
		else {
			uwsgi_log("chmod() socket to 666 for lazy and brave users\n");
			if (chmod(socket_name, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) != 0) {
				uwsgi_error("chmod()");
			}
		}
	}

	free(uws_addr);

	return serverfd;
}

#ifdef UWSGI_UDP
int bind_to_udp(char *socket_name, int multicast, int broadcast) {
	int serverfd;
	struct sockaddr_in uws_addr;
	char *udp_port;
	int bcast = 1;
	int reuse = 1;

#ifdef UWSGI_MULTICAST
	struct ip_mreq mc;
	uint8_t loop = 1;
#endif

	udp_port = strchr(socket_name, ':');
	if (udp_port == NULL) {
		return -1;
	}

	udp_port[0] = 0;

	if (socket_name[0] == 0 && multicast) {
		uwsgi_log("invalid multicast address\n");
		return -1;
	}
	memset(&uws_addr, 0, sizeof(struct sockaddr_in));
	uws_addr.sin_family = AF_INET;
	uws_addr.sin_port = htons(atoi(udp_port + 1));

#ifdef UWSGI_MULTICAST
	if (!broadcast && !multicast) {
		char quad[4];
		char *first_part = strchr(socket_name, '.');
		if (first_part && first_part - socket_name < 4) {
			memset(quad, 0, 4);
			memcpy(quad, socket_name, first_part - socket_name);
			if (atoi(quad) >= 224 && atoi(quad) <= 239) {
				multicast = 1;
			}
		}
#else
	if (!broadcast) {
#endif
		if (!strcmp(socket_name, "255.255.255.255")) {
			broadcast = 1;
		}
	}

	if (broadcast) {
		uws_addr.sin_addr.s_addr = INADDR_BROADCAST;
	}
	else if (socket_name[0] != 0) {
		uws_addr.sin_addr.s_addr = inet_addr(socket_name);
	}
	else {
		uws_addr.sin_addr.s_addr = INADDR_ANY;
	}


	serverfd = socket(AF_INET, SOCK_DGRAM, 0);
	if (serverfd < 0) {
		uwsgi_error("socket()");
		return -1;
	}

	if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEADDR, (const void *) &reuse, sizeof(int)) < 0) {
		uwsgi_error("setsockopt()");
	}

#ifdef UWSGI_MULTICAST
	if (multicast) {
		// if multicast is enabled remember to bind to INADDR_ANY
		uws_addr.sin_addr.s_addr = INADDR_ANY;
		mc.imr_multiaddr.s_addr = inet_addr(socket_name);
		mc.imr_interface.s_addr = INADDR_ANY;
	}
#endif

	if (broadcast) {
		if (setsockopt(serverfd, SOL_SOCKET, SO_BROADCAST, &bcast, sizeof(bcast))) {
			perror("setsockopt");
			close(serverfd);
			return -1;
		}
	}

	if (bind(serverfd, (struct sockaddr *) &uws_addr, sizeof(uws_addr)) != 0) {
		uwsgi_error("bind()");
		close(serverfd);
		return -1;
	}

#ifdef UWSGI_MULTICAST
	if (multicast) {
		uwsgi_log("[uWSGI] joining multicast group: %s:%d\n", socket_name, ntohs(uws_addr.sin_port));
		if (setsockopt(serverfd, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop))) {
			uwsgi_error("setsockopt()");
		}

		if (setsockopt(serverfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mc, sizeof(mc))) {
			uwsgi_error("setsockopt()");
		}

		if (setsockopt(serverfd, IPPROTO_IP, IP_MULTICAST_TTL, &uwsgi.multicast_ttl, sizeof(uwsgi.multicast_ttl))) {
			uwsgi_error("setsockopt()");
		}

	}
#endif

	udp_port[0] = ':';
	return serverfd;

}
#endif

int uwsgi_connectn(char *socket_name, uint16_t len, int timeout, int async) {

	int fd;

	char *zeroed_socket_name = uwsgi_concat2n(socket_name, len, "", 0);
	fd = uwsgi_connect(zeroed_socket_name, timeout, async);

	free(zeroed_socket_name);
	return fd;
}
Esempio n. 16
0
File: rados.c Progetto: Nikolo/uwsgi
static void uwsgi_rados_add_mountpoint(char *arg, size_t arg_len) {
	struct uwsgi_rados_mountpoint *urmp = uwsgi_calloc(sizeof(struct uwsgi_rados_mountpoint));
	if (uwsgi_kvlist_parse(arg, arg_len, ',', '=',
			"mountpoint", &urmp->mountpoint,
			"config", &urmp->config,
			"pool", &urmp->pool,
			"timeout", &urmp->str_timeout,
			"allow_put", &urmp->allow_put,
			"allow_delete", &urmp->allow_delete,
			"allow_mkcol", &urmp->allow_mkcol,
			"allow_propfind", &urmp->allow_propfind,
			"username", &urmp->username,
			"buffer_size", &urmp->str_buffer_size,
			"put_buffer_size", &urmp->str_put_buffer_size,
			NULL)) {
				uwsgi_log("unable to parse rados mountpoint definition\n");
				exit(1);
		}

	if (!urmp->mountpoint|| !urmp->pool) {
		uwsgi_log("[rados] mount requires a mountpoint, and a pool name.\n");
		exit(1);
	}

	if (urmp->str_timeout) {
		urmp->timeout = atoi(urmp->str_timeout);
	}

	if (urmp->str_buffer_size) {
		urmp->buffer_size = atoi(urmp->str_buffer_size);
		if (urmp->buffer_size > MAX_BUF_SIZE) {
			urmp->buffer_size = MAX_BUF_SIZE;
		}
		else if (urmp->buffer_size < MIN_BUF_SIZE) {
			urmp->buffer_size = MIN_BUF_SIZE;
		}
	}
	else {
		urmp->buffer_size = DEF_BUF_SIZE;
	}

	if (urmp->str_put_buffer_size) {
		urmp->put_buffer_size = atoi(urmp->str_put_buffer_size);
		if (urmp->put_buffer_size > MAX_BUF_SIZE) {
			urmp->put_buffer_size = MAX_BUF_SIZE;
		}
		else if (urmp->put_buffer_size < MIN_BUF_SIZE) {
			urmp->put_buffer_size = MIN_BUF_SIZE;
		}
	}
	else {
		urmp->put_buffer_size = urmp->buffer_size;
	}

	time_t now = uwsgi_now();
	uwsgi_log("[rados] mounting %s ...\n", urmp->mountpoint);
	
	rados_t cluster;
	if (rados_create(&cluster, urmp->username) < 0) {
		uwsgi_error("can't create Ceph cluster handle");
		exit(1);
	}
	urmp->cluster = cluster;

	if (urmp->config)
		uwsgi_log("using Ceph conf:%s\n", urmp->config);
	else
		uwsgi_log("using default Ceph conf.\n");

	if (rados_conf_read_file(cluster, urmp->config) < 0) {
		uwsgi_error("can't configure Ceph cluster handle");
		exit(1);
	}

	int timeout = urmp->timeout ? urmp->timeout : urados.timeout;
	char *timeout_str = uwsgi_num2str(timeout);

	rados_conf_set(cluster, "client_mount_timeout", timeout_str);
	rados_conf_set(cluster, "rados_mon_op_timeout", timeout_str);
	rados_conf_set(cluster, "rados_osd_op_timeout", timeout_str);

	free(timeout_str);


	if (rados_connect(cluster) < 0) {
		uwsgi_error("can't connect with Ceph cluster");
		exit(1);
	}


	void *ctx_ptr;

	if (uwsgi.threads > 1) {
		int i;
		rados_ioctx_t *ctxes = uwsgi_calloc(sizeof(rados_ioctx_t) * uwsgi.threads);
		for(i=0;i<uwsgi.threads;i++) {
			if (rados_ioctx_create(cluster, urmp->pool, &ctxes[i]) < 0) {
                        	uwsgi_error("can't open rados pool")
                        	rados_shutdown(cluster);
                        	exit(1);
			}
                }
		ctx_ptr = ctxes;
	}
	else {
		rados_ioctx_t ctx;
		if (rados_ioctx_create(cluster, urmp->pool, &ctx) < 0) {
			uwsgi_error("can't open rados pool")
			rados_shutdown(cluster);
			exit(1);
		}
		ctx_ptr = ctx;
	}

	char fsid[37];
	rados_cluster_fsid(cluster, fsid, 37);
	uwsgi_log("connected to Ceph pool: %s on cluster %.*s\n", urmp->pool, 37, fsid);
	
	int id = uwsgi_apps_cnt;
	struct uwsgi_app *ua = uwsgi_add_app(id, rados_plugin.modifier1, urmp->mountpoint, strlen(urmp->mountpoint), NULL, (void*)1);
	if (!ua) {
		uwsgi_log("[rados] unable to mount %s\n", urmp->mountpoint);
		rados_shutdown(cluster);
		exit(1);
	}

	ua->responder0 = ctx_ptr;
	ua->responder1 = urmp;
	ua->started_at = now;
	ua->startup_time = uwsgi_now() - now;
	uwsgi_log("Rados app/mountpoint %d (%s) loaded in %d seconds at %p\n", id, urmp->mountpoint, (int) ua->startup_time, ctx_ptr);
}
Esempio n. 17
0
static void carbon_post_init() {

	int i;
	struct uwsgi_string_list *usl = u_carbon.servers;
	if (!uwsgi.sockets) return;
	if (!u_carbon.servers) return;

	while(usl) {
		struct carbon_server_list *u_server = uwsgi_calloc(sizeof(struct carbon_server_list));
		u_server->value = usl->value;
		u_server->healthy = 1;
		u_server->errors = 0;
		if (u_carbon.servers_data) {
			u_server->next = u_carbon.servers_data;
		}
		u_carbon.servers_data = u_server;

		uwsgi_log("[carbon] added server %s\n", usl->value);
		usl = usl->next;
	}

	if (!u_carbon.root_node) u_carbon.root_node = "uwsgi.";
	if (strlen(u_carbon.root_node) && !uwsgi_endswith(u_carbon.root_node, ".")) {
		u_carbon.root_node = uwsgi_concat2(u_carbon.root_node, ".");
	}

	if (u_carbon.freq < 1) u_carbon.freq = 60;
	if (u_carbon.timeout < 1) u_carbon.timeout = 3;
	if (u_carbon.max_retries <= 0) u_carbon.max_retries = 1;
	if (u_carbon.retry_delay <= 0) u_carbon.retry_delay = 7;
	if (!u_carbon.id) { 
		u_carbon.id = uwsgi_str(uwsgi.sockets->name);

		for(i=0;i<(int)strlen(u_carbon.id);i++) {
			if (u_carbon.id[i] == '.') u_carbon.id[i] = '_';
		}
	}

	u_carbon.hostname = uwsgi_str(uwsgi.hostname);
	if (u_carbon.hostname_dot_replacement) {
		for(i=0;i<(int)strlen(u_carbon.hostname);i++) {
			if (u_carbon.hostname[i] == '.') u_carbon.hostname[i] = u_carbon.hostname_dot_replacement[0];
		}
	}

	if (!u_carbon.last_busyness_values) {
		u_carbon.last_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
	}

	if (!u_carbon.current_busyness_values) {
		u_carbon.current_busyness_values = uwsgi_calloc(sizeof(unsigned long long) * uwsgi.numproc);
	}

	if (!u_carbon.was_busy) {
		u_carbon.was_busy = uwsgi_calloc(sizeof(int) * uwsgi.numproc);
	}

	// set next update to now()+retry_delay, this way we will have first flush just after start
	u_carbon.last_update = uwsgi_now() - u_carbon.freq + u_carbon.retry_delay;

	uwsgi_log("[carbon] carbon plugin started, %is frequency, %is timeout, max retries %i, retry delay %is\n",
		u_carbon.freq, u_carbon.timeout, u_carbon.max_retries, u_carbon.retry_delay);

	struct uwsgi_stats_pusher_instance *uspi = uwsgi_stats_pusher_add(u_carbon.pusher, NULL);
	uspi->freq = u_carbon.freq;
	// no need to generate the json
	uspi->raw=1;
}