예제 #1
0
void uwsgi_python_harakiri(int wid) {

	if (up.tracebacker) {

        	char buf[8192];
		char *address = uwsgi_concat2(up.tracebacker, uwsgi_num2str(wid));

        	int fd = uwsgi_connect(address, -1, 0);
        	for (;;) {
                	int ret = uwsgi_waitfd(fd, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
                	if (ret <= 0) {
				break;
                	}
                	ssize_t len = read(fd, buf, 8192);
                	if (len <= 0) {
				break;
                	}
                	uwsgi_log("%.*s", (int) len, buf);
        	}

		free(address);
	}

}
예제 #2
0
파일: rados.c 프로젝트: 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);
}
예제 #3
0
void *uwsgi_python_tracebacker_thread(void *foobar) {

	struct iovec iov[9];

	PyObject *new_thread = uwsgi_python_setup_thread("uWSGITraceBacker");
	if (!new_thread) return NULL;

	struct sockaddr_un so_sun;
	socklen_t so_sun_len = 0;

	char *str_wid = uwsgi_num2str(uwsgi.mywid);
	char *sock_path = uwsgi_concat2(up.tracebacker, str_wid);

	int current_defer_accept = uwsgi.no_defer_accept;
        uwsgi.no_defer_accept = 1;
	int fd = bind_to_unix(sock_path, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
        uwsgi.no_defer_accept = current_defer_accept;
	PyObject *threading_module = PyImport_ImportModule("threading");
	if (!threading_module) return NULL;
	//PyObject *threading_dict = PyModule_GetDict(threading_module);

	PyObject *traceback_module = PyImport_ImportModule("traceback");
	if (!traceback_module) return NULL;
	PyObject *traceback_dict = PyModule_GetDict(traceback_module);
	PyObject *extract_stack = PyDict_GetItemString(traceback_dict, "extract_stack");

	PyObject *sys_module = PyImport_ImportModule("sys");
	PyObject *sys_dict = PyModule_GetDict(sys_module);


	PyObject *_current_frames = PyDict_GetItemString(sys_dict, "_current_frames");

	uwsgi_log("python tracebacker for worker %d available on %s\n", uwsgi.mywid, sock_path);
	for(;;) {
		UWSGI_RELEASE_GIL;
		int client_fd = accept(fd, (struct sockaddr *) &so_sun, &so_sun_len);
		if (client_fd < 0) {
			uwsgi_error("accept()");
			UWSGI_GET_GIL;
			continue;
		}
		UWSGI_GET_GIL;
// here is the core of the tracebacker
		PyObject *current_frames = PyEval_CallObject(_current_frames, (PyObject *)NULL);
		if (!current_frames) goto end;
		uwsgi_log("current_frames = %p\n", current_frames);
		PyObject *current_frames_items = PyObject_GetAttrString(current_frames, "items");
		if (!current_frames_items) goto end;
		uwsgi_log("current_frames_items = %p\n", current_frames_items);
		PyObject *frames_ret = PyEval_CallObject(current_frames_items, (PyObject *)NULL);
		if (!frames_ret) goto end;
		uwsgi_log("frames_ret = %p\n", frames_ret);
		PyObject *frames_iter = PyObject_GetIter(frames_ret);
		uwsgi_log("frames_iter = %p\n", frames_iter);
		PyObject *frame = PyIter_Next(frames_iter);
		while(frame) {
			uwsgi_log("frame = %p\n", frame);
			PyObject *stack = PyTuple_GetItem(frame, 1);
			uwsgi_log("stack = %p\n", stack);
			PyObject *arg_tuple = PyTuple_New(1);
			PyTuple_SetItem(arg_tuple, 0, stack);
			PyObject *stacktrace = PyEval_CallObject( extract_stack, arg_tuple);
			uwsgi_log("stacktrace = %p\n", stacktrace);
			PyObject *stacktrace_iter = PyObject_GetIter(stacktrace);
			PyObject *st_items = PyIter_Next(stacktrace_iter);
			while(st_items) {
				uwsgi_log("st_items = %p\n", st_items);
				PyObject *st_filename = PyTuple_GetItem(st_items, 0);
				PyObject *st_lineno = PyTuple_GetItem(st_items, 1);
				PyObject *st_name = PyTuple_GetItem(st_items, 2);
				PyObject *st_line = PyTuple_GetItem(st_items, 3);
				iov[0].iov_base = "filename = ";
				iov[0].iov_len = 11;
				iov[1].iov_base = PyString_AsString(st_filename);
				iov[1].iov_len = strlen(iov[1].iov_base);
				iov[2].iov_base = " lineno = ";
				iov[2].iov_len = 10 ;
				iov[3].iov_base = uwsgi_num2str(PyInt_AsLong(st_lineno));
				iov[3].iov_len = strlen(iov[3].iov_base);
				iov[4].iov_base = " function = ";
				iov[4].iov_len = 12 ;
				iov[5].iov_base = PyString_AsString(st_name);
                                iov[5].iov_len = strlen(iov[5].iov_base);
				iov[6].iov_base = "\n";
				iov[6].iov_len = 1 ;
				if (st_line) {
				}
				if (writev(client_fd, iov, 7) < 0) {
					uwsgi_error("writev()");
				}
				st_items = PyIter_Next(stacktrace_iter);
			}
			frame = PyIter_Next(frames_iter);
		}

	
end:
		close(client_fd);
	}
	return NULL;
}
예제 #4
0
void uwsgi_check_logrotate(void) {

	char message[1024];
	int need_rotation = 0;
	int need_reopen = 0;

	if (uwsgi.log_master) {
		uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
	}
	else {
		uwsgi.shared->logsize = lseek(2, 0, SEEK_CUR);
	}

	if (uwsgi.log_maxsize > 0 && uwsgi.shared->logsize > uwsgi.log_maxsize) {
		need_rotation = 1;
	}
	
	if (uwsgi_check_touches(uwsgi.touch_logrotate)) {
		need_rotation = 1;
	}

	if (uwsgi_check_touches(uwsgi.touch_logreopen)) {
		need_reopen = 1;
	}

	if (need_rotation) {

		char *rot_name = uwsgi.log_backupname;
		int need_free = 0;
		if (rot_name == NULL) {
			char *ts_str = uwsgi_num2str((int) uwsgi_now());
			rot_name = uwsgi_concat3(uwsgi.logfile, ".", ts_str);
			free(ts_str);
			need_free = 1;
		}
		int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering rotation to %s...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize, rot_name);
		if (ret > 0) {
			if (write(uwsgi.original_log_fd, message, ret) != ret) {
				// very probably this will never be printed
				uwsgi_error("write()");
			}
		}
		if (rename(uwsgi.logfile, rot_name) == 0) {
			// reopen logfile dup'it and eventually gracefully reload workers;
			int fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
			if (fd < 0) {
				uwsgi_error_open(uwsgi.logfile);
				grace_them_all(0);
			}
			if (dup2(fd, uwsgi.original_log_fd) < 0) {
				uwsgi_error("dup2()");
				grace_them_all(0);
			}

			close(fd);

		}
		else {
			uwsgi_error("unable to rotate log: rename()");
		}
		if (need_free)
			free(rot_name);
	}
	else if (need_reopen) {
		int ret = snprintf(message, 1024, "[%d] logsize: %llu, triggering log-reopen...\n", (int) uwsgi_now(), (unsigned long long) uwsgi.shared->logsize);
                if (ret > 0) {
                        if (write(uwsgi.original_log_fd, message, ret) != ret) {
                                // very probably this will never be printed
                                uwsgi_error("write()");
                        }
                }

		// reopen logfile;
		close(uwsgi.original_log_fd);
                uwsgi.original_log_fd = open(uwsgi.logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
                if (uwsgi.original_log_fd < 0) {
                	uwsgi_error_open(uwsgi.logfile);
                	grace_them_all(0);
                }
		ret = snprintf(message, 1024, "[%d] %s reopened.\n", (int) uwsgi_now(), uwsgi.logfile);
                if (ret > 0) {
                        if (write(uwsgi.original_log_fd, message, ret) != ret) {
                                // very probably this will never be printed
                                uwsgi_error("write()");
                        }
                }
		uwsgi.shared->logsize = lseek(uwsgi.original_log_fd, 0, SEEK_CUR);
	}
}
예제 #5
0
ssize_t uwsgi_lf_msecs(struct wsgi_request *wsgi_req, char **buf) {
        int microseconds = wsgi_req->end_of_request.tv_sec * 1000000 + wsgi_req->end_of_request.tv_usec;
        int microseconds2 = wsgi_req->start_of_request.tv_sec * 1000000 + wsgi_req->start_of_request.tv_usec;
        *buf = uwsgi_num2str((microseconds - microseconds2)/1000);
        return strlen(*buf);
}
예제 #6
0
ssize_t uwsgi_lf_time(struct wsgi_request *wsgi_req, char **buf) {
        *buf = uwsgi_num2str(wsgi_req->start_of_request.tv_sec);
        return strlen(*buf);
}
예제 #7
0
파일: json.c 프로젝트: apoh/uwsgi
void uwsgi_json_config(char *file, char *magic_table[]) {

	size_t len = 0;
	char *json_data;


	const char *key;

	json_t *root;
	json_error_t error;
	json_t *config;
	json_t *config_value, *config_array_item;

	void *config_iter;

	char *object_asked = "uwsgi";
	char *colon;
	int i;

	if (uwsgi_check_scheme(file)) {
		colon = uwsgi_get_last_char(file, '/');
		colon = uwsgi_get_last_char(colon, ':');
	}
	else {
		colon = uwsgi_get_last_char(file, ':');
	}

	if (colon) {
		colon[0] = 0;
		if (colon[1] != 0) {
			object_asked = colon + 1;
		}
	}

	uwsgi_log_initial("[uWSGI] getting JSON configuration from %s\n", file);

	json_data = uwsgi_open_and_read(file, &len, 1, magic_table);

#ifdef JANSSON_MAJOR_VERSION
	root = json_loads(json_data, 0, &error);
#else
	root = json_loads(json_data, &error);
#endif

	if (!root) {
		uwsgi_log("error parsing JSON data: line %d %s\n", error.line, error.text);
		exit(1);
	}

	config = json_object_get(root, object_asked);

	if (!json_is_object(config)) {
		uwsgi_log("you must define a object named %s in your JSON data\n", object_asked);
		exit(1);
	}

	config_iter = json_object_iter(config);

	while (config_iter) {
		key = json_object_iter_key(config_iter);
		config_value = json_object_iter_value(config_iter);

		if (json_is_string(config_value)) {
			add_exported_option((char *) key, (char *) json_string_value(config_value), 0);
		}
		else if (json_is_true(config_value)) {
			add_exported_option((char *) key, strdup("1"), 0);
		}
		else if (json_is_false(config_value) || json_is_null(config_value)) {
			add_exported_option((char *) key, strdup("0"), 0);
		}
		else if (json_is_integer(config_value)) {
			add_exported_option((char *) key, uwsgi_num2str(json_integer_value(config_value)), 0);
		}
		else if (json_is_array(config_value)) {
			for (i = 0; i < (int) json_array_size(config_value); i++) {
				config_array_item = json_array_get(config_value, i);
				if (json_is_string(config_array_item)) {
					add_exported_option((char *) key, (char *) json_string_value(config_array_item), 0);
				}
				else if (json_is_true(config_array_item)) {
					add_exported_option((char *) key, strdup("1"), 0);
				}
				else if (json_is_false(config_array_item) || json_is_null(config_array_item)) {
					add_exported_option((char *) key, strdup("0"), 0);
				}
				else if (json_is_integer(config_array_item)) {
					add_exported_option((char *) key, uwsgi_num2str(json_integer_value(config_array_item)), 0);
				}
			}
		}

		config_iter = json_object_iter_next(config, config_iter);
	}

	if (colon) colon[0] = ':';

}
예제 #8
0
파일: webdav.c 프로젝트: JuanS/uwsgi
static int uwsgi_webdav_add_props(struct wsgi_request *wsgi_req, xmlNode *req_prop, xmlNode * multistatus, xmlNsPtr dav_ns, char *uri, char *filename, int with_values) {
	struct stat st;
	if (stat(filename, &st)) {
		uwsgi_error("uwsgi_webdav_add_props()/stat()");
		return -1;
	}

	int is_collection = 0;

	xmlNode *response = xmlNewChild(multistatus, dav_ns, BAD_CAST "response", NULL);
	uint16_t uri_len = strlen(uri) ;
	char *encoded_uri = uwsgi_malloc( (uri_len * 3) + 1);
	http_url_encode(uri, &uri_len, encoded_uri);
	encoded_uri[uri_len] = 0;
	xmlNewChild(response, dav_ns, BAD_CAST "href", BAD_CAST encoded_uri);
	free(encoded_uri);
	xmlNode *r_propstat = xmlNewChild(response, dav_ns, BAD_CAST "propstat", NULL);
	char *r_status = uwsgi_concat2n(wsgi_req->protocol, wsgi_req->protocol_len, " 200 OK", 7);
	xmlNewChild(r_propstat, dav_ns, BAD_CAST "status", BAD_CAST r_status);
	free(r_status);

	xmlNode *r_prop = xmlNewChild(r_propstat, dav_ns, BAD_CAST "prop", NULL);

	if (with_values) {
		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "displayname")) {
			char *base_uri = uwsgi_get_last_char(uri, '/');
			if (base_uri) {
				xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", BAD_CAST base_uri+1);
			}
			else {
				xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", BAD_CAST uri);
			}

		}

		if (S_ISDIR(st.st_mode)) is_collection = 1;

		xmlNode *r_type = NULL;

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "resourcetype")) {
			r_type = xmlNewChild(r_prop, dav_ns, BAD_CAST "resourcetype", NULL);
			if (is_collection) {
				xmlNewChild(r_type, dav_ns, BAD_CAST "collection", NULL);
				is_collection = 1;
			}
		}


		if (!is_collection) {
			if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getcontentlength")) {
				char *r_contentlength = uwsgi_num2str(st.st_size);
				xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontentlength", BAD_CAST r_contentlength);
				free(r_contentlength);
			}
			if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getcontenttype")) {
				size_t mime_type_len = 0;
				char *mime_type = uwsgi_get_mime_type(filename, strlen(filename), &mime_type_len);
				if (mime_type) {
					char *r_ctype = uwsgi_concat2n(mime_type, mime_type_len, "", 0);
					xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getcontenttype", BAD_CAST r_ctype);
					free(r_ctype);
				}
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "creationdate")) {
			// there is no creation date on UNIX/POSIX, ctime is the nearest thing...
			char *cdate = uwsgi_webdav_new_date(st.st_ctime);
			if (cdate) {
				xmlNewTextChild(r_prop, dav_ns, BAD_CAST "creationdate", BAD_CAST cdate);
				free(cdate);
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getlastmodified")) {
			char *mdate = uwsgi_webdav_new_date(st.st_mtime);
			if (mdate) {
				xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getlastmodified", BAD_CAST mdate);
				free(mdate);
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "getetag")) {
			char *etag = uwsgi_num2str(st.st_mtime);
			xmlNewTextChild(r_prop, dav_ns, BAD_CAST "getetag", BAD_CAST etag);
			free(etag);
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "executable")) {
			xmlNewChild(r_prop, dav_ns, BAD_CAST "executable", NULL);
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "owner")) {
			xmlNewTextChild(r_prop, dav_ns, BAD_CAST "owner", NULL);
		}

		if (wsgi_req->remote_user_len > 0) {

			if (udav.principal_base) {
				if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "current-user-principal")) {
					char *current_user_principal = uwsgi_concat2n(udav.principal_base, strlen(udav.principal_base), wsgi_req->remote_user, wsgi_req->remote_user_len);
					xmlNode *cup = xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-principal", NULL);
					xmlNewTextChild(cup, dav_ns, BAD_CAST "href", BAD_CAST current_user_principal);
					if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "resourcetype")) {
						if (!strcmp(current_user_principal, uri)) {
							xmlNewChild(r_type, dav_ns, BAD_CAST "principal", NULL);
						}
					}
					free(current_user_principal);
				}
			}

			if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "current-user-privilege-set")) {
				xmlNode *cups = xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-privilege-set", NULL);
				xmlNode *privilege = xmlNewChild(cups, dav_ns, BAD_CAST "privilege", NULL);	
				xmlNewChild(privilege, dav_ns, BAD_CAST "all", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "read", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "write", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "write-content", NULL);
				xmlNewChild(privilege, dav_ns, BAD_CAST "write-properties", NULL);
			}
		}

		if (uwsgi_webdav_prop_requested(req_prop, "DAV:", "supported-report-set")) {
			xmlNode *report_set = xmlNewChild(r_prop, dav_ns, BAD_CAST "supported-report-set", NULL);
			xmlNode *supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "principal-property-search");
			supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "sync-collection");
			supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "expand-property");
			supported_report = xmlNewChild(report_set, dav_ns, BAD_CAST "supported-report", NULL);
			xmlNewChild(supported_report, dav_ns, BAD_CAST "report", BAD_CAST "principal-search-property-set");
		}

		uwsgi_webdav_foreach_prop(udav.add_prop, req_prop, r_prop, 0, NULL );
                uwsgi_webdav_foreach_prop(udav.add_prop_href, req_prop, r_prop, 1, NULL);
                uwsgi_webdav_foreach_prop(udav.add_prop_comp,req_prop, r_prop, 2 , NULL);

		uwsgi_webdav_foreach_prop(udav.add_rtype_prop,req_prop, r_type, 0, "resourcetype");

		if (is_collection) {
			uwsgi_webdav_foreach_prop(udav.add_rtype_collection_prop,req_prop, r_type, 0, "resourcetype");
			uwsgi_webdav_foreach_prop(udav.add_collection_prop,req_prop, r_prop, 0, NULL);
			uwsgi_webdav_foreach_prop(udav.add_collection_prop_href,req_prop, r_prop, 1, NULL);
			uwsgi_webdav_foreach_prop(udav.add_collection_prop_comp,req_prop, r_prop, 2, NULL);
		}
		else {
			uwsgi_webdav_foreach_prop(udav.add_rtype_object_prop,req_prop, r_type, 0, "resourcetype");
			uwsgi_webdav_foreach_prop(udav.add_object_prop,req_prop, r_prop, 0, NULL);
			uwsgi_webdav_foreach_prop(udav.add_object_prop_href,req_prop, r_prop, 1, NULL);
			uwsgi_webdav_foreach_prop(udav.add_object_prop_comp,req_prop, r_prop, 2, NULL);
		}
	}
	else {
		xmlNewChild(r_prop, dav_ns, BAD_CAST "displayname", NULL);
		xmlNewChild(r_prop, dav_ns, BAD_CAST "resourcetype", NULL);
		if (!S_ISDIR(st.st_mode)) {
			xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontentlength", NULL);
			xmlNewChild(r_prop, dav_ns, BAD_CAST "getcontenttype", NULL);
		}
		xmlNewChild(r_prop, dav_ns, BAD_CAST "creationdate", NULL);
		xmlNewChild(r_prop, dav_ns, BAD_CAST "getlastmodified", NULL);
		xmlNewChild(r_prop, dav_ns, BAD_CAST "supported-report-set", NULL);
		if (wsgi_req->remote_user_len > 0) {
			xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-privilege-set", NULL);
			if (udav.principal_base) {
				xmlNewChild(r_prop, dav_ns, BAD_CAST "current-user-principal", NULL);
			}
		}
	}

#if defined(__linux__) || defined(__APPLE__)
	// get xattr for user.uwsgi.webdav.
#if defined(__linux__)
	ssize_t rlen = listxattr(filename, NULL, 0);
#elif defined(__APPLE__)
	ssize_t rlen = listxattr(filename, NULL, 0, 0);
#endif
	// do not return -1 as the previous xml is valid !!!
	if (rlen <= 0) return 0;
	// use calloc to avoid races
	char *xattrs = uwsgi_calloc(rlen);
#if defined(__linux__)
	if (listxattr(filename, xattrs, rlen) <= 0) {
#elif defined(__APPLE__)
	if (listxattr(filename, xattrs, rlen, 0) <= 0) {
#endif
		free(xattrs);
		return 0;
	}
	// parse the name list
	ssize_t i;
	char *key = NULL;
	for(i=0;i<rlen;i++) {
		// check for wrong condition
		if (xattrs[i] == 0 && key == NULL) break;
		if (key && xattrs[i] == 0) {
			if (!uwsgi_starts_with(key, strlen(key), "user.uwsgi.webdav.", 18)) {
				if (uwsgi_string_list_has_item(udav.skip_prop, key + 18, strlen(key + 18))) continue;
				xmlNsPtr xattr_ns = NULL;
				// does it has a namespace ?
				char *separator = strchr(key + 18, '|');
				char *xattr_key = key + 18;
				if (separator) {
					xattr_key = separator + 1;
					*separator = 0;
					if (!uwsgi_webdav_prop_requested(req_prop, key + 18, xattr_key)) continue;
				}
				else {
					if (!uwsgi_webdav_prop_requested(req_prop, NULL, xattr_key)) continue;
				}
				xmlNode *xattr_item = NULL;
				if (with_values) {
#if defined(__linux__)
					ssize_t rlen2 = getxattr(filename, key, NULL, 0);
#elif defined(__APPLE__)
					ssize_t rlen2 = getxattr(filename, key, NULL, 0, 0, 0);
#endif
					if (rlen > 0) {
						// leave space for final 0
						char *xvalue = uwsgi_calloc(rlen2 + 1);
#if defined(__linux__)
						if (getxattr(filename, key, xvalue, rlen2) > 0) {
#elif defined(__APPLE__)
						if (getxattr(filename, key, xvalue, rlen2, 0 ,0) > 0) {
#endif
							xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, BAD_CAST xvalue);
						}
						free(xvalue);	
					}
					else if (rlen == 0) {
						xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, NULL);
					}
				}
				else {
					xattr_item = xmlNewTextChild(r_prop, NULL, BAD_CAST xattr_key, NULL);
				}	
				if (separator && xattr_item) {
					xattr_ns = xmlNewNs(xattr_item, BAD_CAST (key + 18), NULL);
					*separator = '|';
					xmlSetNs(xattr_item, xattr_ns);	
				}
			}
			key = NULL;
		}
		else if (key == NULL) {
			key = &xattrs[i];
		}
	}
	free(xattrs);
	
#endif
	return 0;
}

static size_t uwsgi_webdav_expand_path(struct wsgi_request *wsgi_req, char *item, uint16_t item_len, char *filename) {
	struct uwsgi_app *ua = &uwsgi_apps[wsgi_req->app_id];
	char *docroot = ua->interpreter;
	size_t docroot_len = strlen(docroot);

	// merge docroot with path_info
	char *tmp_filename = uwsgi_concat3n(docroot, docroot_len, "/", 1, item, item_len);
	// try expanding the path 
	if (!realpath(tmp_filename, filename)) {
		free(tmp_filename);
		return 0;
	}
	free(tmp_filename);
	return strlen(filename);
}

static size_t uwsgi_webdav_expand_fake_path(struct wsgi_request *wsgi_req, char *item, uint16_t item_len, char *filename) {
	char *last_slash = uwsgi_get_last_charn(item, item_len, '/');
        if (!last_slash) return 0;
        size_t filename_len = uwsgi_webdav_expand_path(wsgi_req, item, last_slash - item, filename);
        if (!filename_len) return 0;
        // check for overflow
        if (filename_len + (item_len - (last_slash - item)) >= PATH_MAX) return 0;
        memcpy(filename + filename_len, last_slash, (item_len - (last_slash - item)));
        filename_len += (item_len - (last_slash - item));
        filename[(int)filename_len] = 0;
	return filename_len;
}

static xmlDoc *uwsgi_webdav_manage_prop(struct wsgi_request *wsgi_req, xmlNode *req_prop, char *filename, size_t filename_len, int with_values) {
	// default 1 depth
	int depth = 1;
        uint16_t http_depth_len = 0;
        char *http_depth = uwsgi_get_var(wsgi_req, "HTTP_DEPTH", 10, &http_depth_len);
        if (http_depth) {
                depth = uwsgi_str_num(http_depth, http_depth_len);
        }

	xmlDoc *rdoc = xmlNewDoc(BAD_CAST "1.0");
        xmlNode *multistatus = xmlNewNode(NULL, BAD_CAST "multistatus");
        xmlDocSetRootElement(rdoc, multistatus);
        xmlNsPtr dav_ns = xmlNewNs(multistatus, BAD_CAST "DAV:", BAD_CAST "D");
        xmlSetNs(multistatus, dav_ns);

	if (depth == 0) {
                char *uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
                uwsgi_webdav_add_props(wsgi_req, req_prop, multistatus, dav_ns, uri, filename, with_values);
                free(uri);
        }
        else {
                DIR *collection = opendir(filename);
                struct dirent de;
                for (;;) {
                        struct dirent *de_r = NULL;
                        if (readdir_r(collection, &de, &de_r)) {
                                uwsgi_error("uwsgi_wevdav_manage_propfind()/readdir_r()");
                                break;
                        }
                        if (de_r == NULL) {
                                break;
                        }
                        char *uri = NULL;
                        char *direntry = NULL;
                        if (!strcmp(de.d_name, "..")) {
                                // skip ..
                                continue;
                        }
                        else if (!strcmp(de.d_name, ".")) {
                                uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, "", 0);
                                direntry = uwsgi_concat2n(filename, filename_len, "", 0);
                        }
                        else if (wsgi_req->path_info[wsgi_req->path_info_len - 1] == '/') {
                                uri = uwsgi_concat2n(wsgi_req->path_info, wsgi_req->path_info_len, de.d_name, strlen(de.d_name));
                                direntry = uwsgi_concat3n(filename, filename_len, "/", 1, de.d_name, strlen(de.d_name));
                        }
                        else {
                                uri = uwsgi_concat3n(wsgi_req->path_info, wsgi_req->path_info_len, "/", 1, de.d_name, strlen(de.d_name));
                                direntry = uwsgi_concat3n(filename, filename_len, "/", 1, de.d_name, strlen(de.d_name));
                        }
                        uwsgi_webdav_add_props(wsgi_req, req_prop, multistatus, dav_ns, uri, direntry, with_values);
                        free(uri);
                        free(direntry);
                }
                closedir(collection);
        }

	return rdoc;
	
}
예제 #9
0
파일: lock.c 프로젝트: Nikolo/uwsgi
void uwsgi_setup_locking() {

	int i;

	if (uwsgi.locking_setup) return;

	// use the fastest available locking
	if (uwsgi.lock_engine) {
		if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
			uwsgi_log_initial("lock engine: ipcsem\n");
			atexit(uwsgi_ipcsem_clear);
			uwsgi.lock_ops.lock_init = uwsgi_lock_ipcsem_init;
			uwsgi.lock_ops.lock_check = uwsgi_lock_ipcsem_check;
			uwsgi.lock_ops.lock = uwsgi_lock_ipcsem;
			uwsgi.lock_ops.unlock = uwsgi_unlock_ipcsem;
			uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_ipcsem_init;
			uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_ipcsem_check;
			uwsgi.lock_ops.rlock = uwsgi_rlock_ipcsem;
			uwsgi.lock_ops.wlock = uwsgi_wlock_ipcsem;
			uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
			uwsgi.lock_size = 8;
			uwsgi.rwlock_size = 8;
			goto ready;
		}
		uwsgi_log("unable to find lock engine \"%s\"\n", uwsgi.lock_engine);
		exit(1);
	}

	uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
#ifdef UWSGI_IPCSEM_ATEXIT
	atexit(uwsgi_ipcsem_clear);
#endif
	uwsgi.lock_ops.lock_init = uwsgi_lock_fast_init;
	uwsgi.lock_ops.lock_check = uwsgi_lock_fast_check;
	uwsgi.lock_ops.lock = uwsgi_lock_fast;
	uwsgi.lock_ops.unlock = uwsgi_unlock_fast;
	uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_fast_init;
	uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_fast_check;
	uwsgi.lock_ops.rlock = uwsgi_rlock_fast;
	uwsgi.lock_ops.wlock = uwsgi_wlock_fast;
	uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_fast;
	uwsgi.lock_size = UWSGI_LOCK_SIZE;
	uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;

ready:
	// application generic lock
	uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
	for (i = 0; i < uwsgi.locks + 1; i++) {
		char *num = uwsgi_num2str(i);
		uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", num));
		free(num);
	}

	// event queue lock (mitigate same event on multiple queues)
	if (uwsgi.threads > 1) {
		pthread_mutex_init(&uwsgi.thunder_mutex, NULL);
	}

	if (uwsgi.master_process) {
		// signal table lock
		uwsgi.signal_table_lock = uwsgi_lock_init("signal");

		// fmon table lock
		uwsgi.fmon_table_lock = uwsgi_lock_init("filemon");

		// timer table lock
		uwsgi.timer_table_lock = uwsgi_lock_init("timer");

		// rb_timer table lock
		uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");

		// cron table lock
		uwsgi.cron_table_lock = uwsgi_lock_init("cron");
	}

	if (uwsgi.use_thunder_lock) {
		// process shared thunder lock
		uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");	
#ifdef UNBIT
		// we have a serious bug on Unbit (and very probably on older libc)
		// when all of the workers die in the same moment the pthread robust mutes is left
		// in inconsistent state and we have no way to recover
		// we span a thread in the master constantly ensuring the lock is ok
		// for now we apply it only for Unbit (where thunder-lock is automatically enabled)
		uwsgi_robust_mutexes_watchdog();		
#endif
	}

	uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");

#ifdef UWSGI_SSL
	// register locking for legions
	struct uwsgi_legion *ul = uwsgi.legions;
	while(ul) {
		ul->lock = uwsgi_lock_init(uwsgi_concat2("legion_", ul->legion));
		ul = ul->next;
	}
#endif
	uwsgi.locking_setup = 1;
}
예제 #10
0
파일: emperor.c 프로젝트: ahua/c
int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {

	int i;
	char *colon = NULL;
	int counter;
	char **uenvs;
	char *uef;
	char **vassal_argv;
	pid_t pid;

	if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
		uwsgi_error("socketpair()");
		return -1;
	}

	event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]);

	if (n_ui->use_config) {
		if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
			uwsgi_error("socketpair()");
			return -1;
		}
	}

	if (n_ui->zerg) {
		uwsgi.emperor_broodlord_num++;
	}

	// TODO pre-start hook

	// a new uWSGI instance will start 
	pid = fork();
	if (pid < 0) {
		uwsgi_error("fork()")
	}
	else if (pid > 0) {
		n_ui->pid = pid;
		// close the right side of the pipe
		close(n_ui->pipe[1]);
		// close the "on demand" socket
		if (n_ui->on_demand_fd > -1) {
			close(n_ui->on_demand_fd);
			n_ui->on_demand_fd = -1;
		}
		if (n_ui->use_config) {
			close(n_ui->pipe_config[1]);
		}

		if (n_ui->use_config) {
			struct uwsgi_header uh;
			uh.modifier1 = 115;
                	uh.pktsize = n_ui->config_len;
                	uh.modifier2 = 0;
                	if (write(n_ui->pipe_config[0], &uh, 4) != 4) {
                        	uwsgi_error("[uwsgi-emperor] write() header config");
                	}
                	else {
                        	if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) != (long) n_ui->config_len) {
                                	uwsgi_error("[uwsgi-emperor] write() config");
                        	}
                	}

		}
		return 0;
	}
	else {

		if (uwsgi.emperor_tyrant) {
			uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) n_ui->uid, (int) n_ui->gid, n_ui->name);
			if (setgid(n_ui->gid)) {
				uwsgi_error("setgid()");
				exit(1);
			}
			if (setgroups(0, NULL)) {
				uwsgi_error("setgroups()");
				exit(1);
			}

			if (setuid(n_ui->uid)) {
				uwsgi_error("setuid()");
				exit(1);
			}

		}

		unsetenv("UWSGI_RELOADS");
		unsetenv("NOTIFY_SOCKET");

		uef = uwsgi_num2str(n_ui->pipe[1]);
		if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
			uwsgi_error("setenv()");
			exit(1);
		}
		free(uef);

		// add UWSGI_BROODLORD_NUM
		if (n_ui->zerg) {
			uef = uwsgi_num2str(uwsgi.emperor_broodlord_num);
			if (setenv("UWSGI_BROODLORD_NUM", uef, 1)) {
                        	uwsgi_error("setenv()");
                        	exit(1);
                	}
                	free(uef);
		}

		if (n_ui->use_config) {
			uef = uwsgi_num2str(n_ui->pipe_config[1]);
			if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
				uwsgi_error("setenv()");
				exit(1);
			}
			free(uef);
		}

		uenvs = environ;
		while (*uenvs) {
			if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
				char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
				char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
				if (unsetenv(oe)) {
					uwsgi_error("unsetenv()");
					free(oe);
					break;
				}
				free(oe);
#ifdef UWSGI_DEBUG
				uwsgi_log("putenv %s\n", ne);
#endif

				if (putenv(ne)) {
					uwsgi_error("putenv()");
				}
				// do not free ne as putenv will add it to the environ
				uenvs = environ;
				continue;
			}
			uenvs++;
		}

		// close the left side of the pipe
		close(n_ui->pipe[0]);

		if (n_ui->use_config) {
			close(n_ui->pipe_config[0]);
		}

		counter = 4;
		struct uwsgi_string_list *uct = uwsgi.vassals_templates;
		while (uct) {
			counter += 2;
			uct = uct->next;
		}

		vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
		// set args
		vassal_argv[0] = uwsgi.binary_path;

		if (uwsgi.emperor_broodlord) {
			colon = strchr(n_ui->name, ':');
			if (colon) {
				colon[0] = 0;
			}
		}
		// initialize to a default value
		vassal_argv[1] = "--inherit";

		if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".xml"))
			vassal_argv[1] = "--xml";
		if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".ini"))
			vassal_argv[1] = "--ini";
		if (!strcmp(n_ui->name + (strlen(n_ui->name) - 4), ".yml"))
			vassal_argv[1] = "--yaml";
		if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".yaml"))
			vassal_argv[1] = "--yaml";
		if (!strcmp(n_ui->name + (strlen(n_ui->name) - 3), ".js"))
			vassal_argv[1] = "--json";
		if (!strcmp(n_ui->name + (strlen(n_ui->name) - 5), ".json"))
			vassal_argv[1] = "--json";
	
		struct uwsgi_string_list *usl = uwsgi.emperor_extra_extension;
		while(usl) {
			if (uwsgi_endswith(n_ui->name, usl->value)) {
				vassal_argv[1] = "--config";
				break;
			}
			usl = usl->next;
		}

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


		vassal_argv[2] = n_ui->name;
		if (uwsgi.emperor_magic_exec) {
			if (!access(n_ui->name, R_OK | X_OK)) {
				vassal_argv[2] = uwsgi_concat2("exec://", n_ui->name);
			}

		}

		if (n_ui->use_config) {
			vassal_argv[2] = uwsgi_concat2("emperor://", n_ui->name);
		}

		counter = 3;
		uct = uwsgi.vassals_templates;
		while (uct) {
			vassal_argv[counter] = "--inherit";
			vassal_argv[counter + 1] = uct->value;
			counter += 2;
			uct = uct->next;
		}
		vassal_argv[counter] = NULL;

		// disable stdin OR map it to the "on demand" socket
		if (n_ui->on_demand_fd > -1) {
			if (n_ui->on_demand_fd != 0) {
				if (dup2(n_ui->on_demand_fd, 0) < 0) {
                                        uwsgi_error("dup2()");
                                        exit(1);
                                }
                                close(n_ui->on_demand_fd);
			}
		}
		else {
			int stdin_fd = open("/dev/null", O_RDONLY);
			if (stdin_fd < 0) {
				uwsgi_error_open("/dev/null");
				exit(1);
			}
			if (stdin_fd != 0) {
				if (dup2(stdin_fd, 0) < 0) {
					uwsgi_error("dup2()");
					exit(1);
				}
				close(stdin_fd);
			}
		}

		// close all of the unneded fd
		for (i = 3; i < (int) uwsgi.max_fd; i++) {
			if (n_ui->use_config) {
				if (i == n_ui->pipe_config[1])
					continue;
			}
			if (i != n_ui->pipe[1]) {
				close(i);
			}
		}

		if (uwsgi.vassals_start_hook) {
			uwsgi_log("[emperor] running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
			if (uwsgi.emperor_absolute_dir) {
				if (setenv("UWSGI_VASSALS_DIR", uwsgi.emperor_absolute_dir, 1)) {
					uwsgi_error("setenv()");
				}
			}
			int start_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_start_hook, n_ui->name);
			uwsgi_log("[emperor] %s start-hook returned %d\n", n_ui->name, start_hook_ret);
		}

		// start !!!
		if (execvp(vassal_argv[0], vassal_argv)) {
			uwsgi_error("execvp()");
		}
		uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n");
		// never here
		exit(UWSGI_EXILE_CODE);
	}

	return -1;
}
예제 #11
0
struct uwsgi_socket *uwsgi_new_socket(char *name) {

	struct uwsgi_socket *uwsgi_sock = uwsgi.sockets, *old_uwsgi_sock;
	struct sockaddr_in sin;
	socklen_t socket_type_len;

	if (!uwsgi_sock) {
		uwsgi.sockets = uwsgi_malloc(sizeof(struct uwsgi_socket));
		uwsgi_sock = uwsgi.sockets;
	}
	else {
		while (uwsgi_sock) {
			old_uwsgi_sock = uwsgi_sock;
			uwsgi_sock = uwsgi_sock->next;
		}

		uwsgi_sock = uwsgi_malloc(sizeof(struct uwsgi_socket));
		old_uwsgi_sock->next = uwsgi_sock;
	}

	memset(uwsgi_sock, 0, sizeof(struct uwsgi_socket));
	uwsgi_sock->name = name;
	uwsgi_sock->fd = -1;

	if (!name)
		return uwsgi_sock;

	if (name[0] == '=') {
		int shared_socket = atoi(uwsgi_sock->name + 1);
		if (shared_socket >= 0) {
			struct uwsgi_socket *uss = uwsgi_get_shared_socket_by_num(shared_socket);
			if (!uss) {
				uwsgi_log("unable to use shared socket %d\n", shared_socket);
				exit(1);
			}
			uwsgi_sock->bound = 1;
			uwsgi_sock->shared = 1;
			uwsgi_sock->from_shared = shared_socket;
			return uwsgi_sock;
		}
	}

	if (!uwsgi_startswith(name, "fd://", 5)) {
		uwsgi_add_socket_from_fd(uwsgi_sock, atoi(name + 5));
		return uwsgi_sock;
	}

	char *tcp_port = strrchr(name, ':');
	if (tcp_port) {
		// INET socket, check for 0 port
		if (tcp_port[1] == 0 || tcp_port[1] == '0') {
			uwsgi_sock->fd = bind_to_tcp(name, uwsgi.listen_queue, tcp_port);
			uwsgi_sock->family = AF_INET;
			uwsgi_sock->bound = 1;

			uwsgi_sock->auto_port = 1;

			socket_type_len = sizeof(struct sockaddr_in);

			if (getsockname(uwsgi_sock->fd, (struct sockaddr *) &sin, &socket_type_len)) {
				uwsgi_error("getsockname()");
				exit(1);
			}


			char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
			uwsgi_sock->name = uwsgi_concat3n(name, tcp_port - name, ":", 1, auto_port, strlen(auto_port));
		}
		// is it fd 0 ?
		else if (tcp_port[1] == ':') {
			uwsgi_sock->fd = 0;
			uwsgi_sock->family = AF_INET;
			uwsgi_sock->bound = 1;

			socket_type_len = sizeof(struct sockaddr_in);

			if (getsockname(0, (struct sockaddr *) &sin, &socket_type_len)) {
				uwsgi_error("getsockname()");
				exit(1);
			}


			char *auto_port = uwsgi_num2str(ntohs(sin.sin_port));
			char *auto_ip = inet_ntoa(sin.sin_addr);
			uwsgi_sock->name = uwsgi_concat3n(auto_ip, strlen(auto_ip), ":", 1, auto_port, strlen(auto_port));
		}
	}

	return uwsgi_sock;
}
예제 #12
0
파일: tracebacker.c 프로젝트: Algy/uwsgi
void *uwsgi_python_tracebacker_thread(void *foobar) {

	struct iovec iov[11];

	PyObject *new_thread = uwsgi_python_setup_thread("uWSGITraceBacker");
	if (!new_thread) return NULL;

	struct sockaddr_un so_sun;
	socklen_t so_sun_len = 0;

	char *str_wid = uwsgi_num2str(uwsgi.mywid);
	char *sock_path = uwsgi_concat2(up.tracebacker, str_wid);

	int current_defer_accept = uwsgi.no_defer_accept;
        uwsgi.no_defer_accept = 1;
	int fd = bind_to_unix(sock_path, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
	if (fd < 0) {
		uwsgi.no_defer_accept = current_defer_accept;
		free(str_wid);
		free(sock_path);
		return NULL;
	}
        uwsgi.no_defer_accept = current_defer_accept;

	PyObject *traceback_module = PyImport_ImportModule("traceback");
	if (!traceback_module) {
		free(str_wid);
		free(sock_path);
		close(fd);
		return NULL;
	}
	PyObject *traceback_dict = PyModule_GetDict(traceback_module);
	PyObject *extract_stack = PyDict_GetItemString(traceback_dict, "extract_stack");

	PyObject *sys_module = PyImport_ImportModule("sys");
	PyObject *sys_dict = PyModule_GetDict(sys_module);

	PyObject *_current_frames = PyDict_GetItemString(sys_dict, "_current_frames");

	uwsgi_log("python tracebacker for worker %d available on %s\n", uwsgi.mywid, sock_path);

	for(;;) {
		UWSGI_RELEASE_GIL;
		int client_fd = accept(fd, (struct sockaddr *) &so_sun, &so_sun_len);
		if (client_fd < 0) {
			uwsgi_error("accept()");
			UWSGI_GET_GIL;
			continue;
		}
		UWSGI_GET_GIL;
// here is the core of the tracebacker
		PyObject *current_frames = PyEval_CallObject(_current_frames, (PyObject *)NULL);
		if (!current_frames) goto end2;

		PyObject *current_frames_items = PyObject_GetAttrString(current_frames, "items");
		if (!current_frames_items) goto end;

		PyObject *frames_ret = PyEval_CallObject(current_frames_items, (PyObject *)NULL);
		if (!frames_ret) goto end3;

		PyObject *frames_iter = PyObject_GetIter(frames_ret);
		if (!frames_iter) goto end4;


		// we have the first frame, lets parse it
		if (write(client_fd, "*** uWSGI Python tracebacker output ***\n\n", 41) < 0) {
			uwsgi_error("write()");
		}
		PyObject *frame = PyIter_Next(frames_iter);
		while(frame) {
			PyObject *thread_id = PyTuple_GetItem(frame, 0);
			if (!thread_id) goto next2;

			PyObject *stack = PyTuple_GetItem(frame, 1);
			if (!stack) goto next2;

			PyObject *arg_tuple = PyTuple_New(1);
			PyTuple_SetItem(arg_tuple, 0, stack);
			Py_INCREF(stack);
			PyObject *stacktrace = PyEval_CallObject( extract_stack, arg_tuple);
			Py_DECREF(arg_tuple);
			if (!stacktrace) goto next2;
			
			PyObject *stacktrace_iter = PyObject_GetIter(stacktrace);
			if (!stacktrace_iter) { Py_DECREF(stacktrace); goto next2;}

			PyObject *st_items = PyIter_Next(stacktrace_iter);
			// we have the first traceback item
			while(st_items) {
#ifdef PYTHREE
				int thread_name_need_free = 0;
#endif
				PyObject *st_filename = PyTuple_GetItem(st_items, 0);
				if (!st_filename) { Py_DECREF(st_items); goto next; }
				PyObject *st_lineno = PyTuple_GetItem(st_items, 1);
				if (!st_lineno) {Py_DECREF(st_items); goto next;}
				PyObject *st_name = PyTuple_GetItem(st_items, 2);
				if (!st_name) {Py_DECREF(st_items); goto next;}

				PyObject *st_line = PyTuple_GetItem(st_items, 3);

				iov[0].iov_base = "thread_id = ";
				iov[0].iov_len = 12;

				iov[1].iov_base = uwsgi_python_get_thread_name(thread_id);
				if (!iov[1].iov_base) {
					iov[1].iov_base = "<UnnamedPythonThread>";
				}
#ifdef PYTHREE
				else {
					thread_name_need_free = 1;
				}
#endif
				iov[1].iov_len = strlen(iov[1].iov_base);

				iov[2].iov_base = " filename = ";
				iov[2].iov_len = 12;

#ifdef PYTHREE
				PyObject *st_filename_utf8 = PyUnicode_AsUTF8String(st_filename);
				if (!st_filename_utf8) {
					if (thread_name_need_free) free(iov[1].iov_base);
					goto next;
				}
				iov[3].iov_base = PyString_AsString(st_filename_utf8);
#else
				iov[3].iov_base = PyString_AsString(st_filename);
#endif
				iov[3].iov_len = strlen(iov[3].iov_base);

				iov[4].iov_base = " lineno = ";
				iov[4].iov_len = 10 ;

				iov[5].iov_base = uwsgi_num2str(PyInt_AsLong(st_lineno));
				iov[5].iov_len = strlen(iov[5].iov_base);

				iov[6].iov_base = " function = ";
				iov[6].iov_len = 12 ;

#ifdef PYTHREE
                                PyObject *st_name_utf8 = PyUnicode_AsUTF8String(st_name);
                                if (!st_name_utf8) {
					if (thread_name_need_free) free(iov[1].iov_base);
					Py_DECREF(st_filename_utf8);
					goto next;
				}
				iov[7].iov_base = PyString_AsString(st_name_utf8);
#else
				iov[7].iov_base = PyString_AsString(st_name);
#endif
                                iov[7].iov_len = strlen(iov[7].iov_base);

				iov[8].iov_base = "";
				iov[8].iov_len = 0 ;

				iov[9].iov_base = "";
				iov[9].iov_len = 0;

				iov[10].iov_base = "\n";
				iov[10].iov_len = 1;

#ifdef PYTHREE
				PyObject *st_line_utf8 = NULL;
#endif
				if (st_line) {
					iov[8].iov_base = " line = ";
					iov[8].iov_len = 8;
#ifdef PYTHREE
                                	PyObject *st_line_utf8 = PyUnicode_AsUTF8String(st_line);
                                	if (!st_line_utf8) {
						if (thread_name_need_free) free(iov[1].iov_base);
                                        	Py_DECREF(st_filename_utf8);
                                        	Py_DECREF(st_name_utf8);
                                        	goto next;
                                	}
					iov[9].iov_base = PyString_AsString(st_line_utf8);
#else
					iov[9].iov_base = PyString_AsString(st_line);
#endif
					iov[9].iov_len = strlen(iov[9].iov_base);
				}

				if (writev(client_fd, iov, 11) < 0) {
					uwsgi_error("writev()");
				}

				// free the line_no
				free(iov[5].iov_base);
				Py_DECREF(st_items);
#ifdef PYTHREE
				Py_DECREF(st_filename_utf8);
				Py_DECREF(st_name_utf8);
				if (st_line_utf8) {
					Py_DECREF(st_line_utf8);
				}
				if (thread_name_need_free)
					free(iov[1].iov_base);
#endif
				st_items = PyIter_Next(stacktrace_iter);
			}
			if (write(client_fd, "\n", 1) < 0) {
				uwsgi_error("write()");
			}
next:
			Py_DECREF(stacktrace_iter);
			Py_DECREF(stacktrace);
next2:
			Py_DECREF(frame);
			frame = PyIter_Next(frames_iter);
		}

		Py_DECREF(frames_iter);
end4:	
		Py_DECREF(frames_ret);
end3:	
		Py_DECREF(current_frames_items);
end:
		Py_DECREF(current_frames);
end2:
		close(client_fd);
	}
	return NULL;
}
예제 #13
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;
			}
		}	
예제 #14
0
ssize_t uwsgi_lf_msecs(struct wsgi_request *wsgi_req, char **buf) {
        *buf = uwsgi_num2str((wsgi_req->end_of_request-wsgi_req->start_of_request)/1000);
        return strlen(*buf);
}
예제 #15
0
파일: lock.c 프로젝트: thrashaholic/uwsgi
void uwsgi_setup_locking() {

	int i;

	if (uwsgi.locking_setup) return;

	// use the fastest available locking
	if (uwsgi.lock_engine) {
		if (!strcmp(uwsgi.lock_engine, "ipcsem")) {
			uwsgi_log_initial("lock engine: ipcsem\n");
			atexit(uwsgi_ipcsem_clear);
			uwsgi.lock_ops.lock_init = uwsgi_lock_ipcsem_init;
			uwsgi.lock_ops.lock_check = uwsgi_lock_ipcsem_check;
			uwsgi.lock_ops.lock = uwsgi_lock_ipcsem;
			uwsgi.lock_ops.unlock = uwsgi_unlock_ipcsem;
			uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_ipcsem_init;
			uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_ipcsem_check;
			uwsgi.lock_ops.rlock = uwsgi_rlock_ipcsem;
			uwsgi.lock_ops.wlock = uwsgi_wlock_ipcsem;
			uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_ipcsem;
			uwsgi.lock_size = 8;
			uwsgi.rwlock_size = 8;
			goto ready;
		}
		uwsgi_log("unable to find lock engine \"%s\"\n", uwsgi.lock_engine);
		exit(1);
	}

	uwsgi_log_initial("lock engine: %s\n", UWSGI_LOCK_ENGINE_NAME);
#ifdef UWSGI_IPCSEM_ATEXIT
	atexit(uwsgi_ipcsem_clear);
#endif
	uwsgi.lock_ops.lock_init = uwsgi_lock_fast_init;
	uwsgi.lock_ops.lock_check = uwsgi_lock_fast_check;
	uwsgi.lock_ops.lock = uwsgi_lock_fast;
	uwsgi.lock_ops.unlock = uwsgi_unlock_fast;
	uwsgi.lock_ops.rwlock_init = uwsgi_rwlock_fast_init;
	uwsgi.lock_ops.rwlock_check = uwsgi_rwlock_fast_check;
	uwsgi.lock_ops.rlock = uwsgi_rlock_fast;
	uwsgi.lock_ops.wlock = uwsgi_wlock_fast;
	uwsgi.lock_ops.rwunlock = uwsgi_rwunlock_fast;
	uwsgi.lock_size = UWSGI_LOCK_SIZE;
	uwsgi.rwlock_size = UWSGI_RWLOCK_SIZE;

ready:
	// application generic lock
	uwsgi.user_lock = uwsgi_malloc(sizeof(void *) * (uwsgi.locks + 1));
	for (i = 0; i < uwsgi.locks + 1; i++) {
		uwsgi.user_lock[i] = uwsgi_lock_init(uwsgi_concat2("user ", uwsgi_num2str(i)));
	}

	// event queue lock (mitigate same event on multiple queues)
	if (uwsgi.threads > 1) {
		pthread_mutex_init(&uwsgi.thunder_mutex, NULL);
	}

	if (uwsgi.master_process) {
		// signal table lock
		uwsgi.signal_table_lock = uwsgi_lock_init("signal");

		// fmon table lock
		uwsgi.fmon_table_lock = uwsgi_lock_init("filemon");

		// timer table lock
		uwsgi.timer_table_lock = uwsgi_lock_init("timer");

		// rb_timer table lock
		uwsgi.rb_timer_table_lock = uwsgi_lock_init("rbtimer");

		// cron table lock
		uwsgi.cron_table_lock = uwsgi_lock_init("cron");
	}

	if (uwsgi.use_thunder_lock) {
		// process shared thunder lock
		uwsgi.the_thunder_lock = uwsgi_lock_init("thunder");	
	}

	uwsgi.rpc_table_lock = uwsgi_lock_init("rpc");

#ifdef UWSGI_SSL
	// register locking for legions
	struct uwsgi_legion *ul = uwsgi.legions;
	while(ul) {
		ul->lock = uwsgi_lock_init(uwsgi_concat2("legion_", ul->legion));
		ul = ul->next;
	}
#endif
	uwsgi.locking_setup = 1;
}
예제 #16
0
파일: webdav.c 프로젝트: JuanS/uwsgi
static int uwsgi_wevdav_manage_get(struct wsgi_request *wsgi_req, int send_body) {
	char filename[PATH_MAX];
	size_t filename_len = uwsgi_webdav_expand_path(wsgi_req, wsgi_req->path_info, wsgi_req->path_info_len, filename);
	if (!filename_len) {
		uwsgi_404(wsgi_req);
		return UWSGI_OK;
	}

	if (uwsgi_is_dir(filename)) {
		uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6);
		if (send_body) {
			uwsgi_webdav_dirlist(wsgi_req, filename);
		}
		return UWSGI_OK;
	}

	int fd = open(filename, O_RDONLY);
	if (fd < 0) {
		uwsgi_403(wsgi_req);
		return UWSGI_OK;
	}
	struct stat st;
	if (fstat(fd, &st)) {
		close(fd);
		uwsgi_403(wsgi_req);
		return UWSGI_OK;
	}

	if (uwsgi_response_prepare_headers(wsgi_req, "200 OK", 6))
		goto end;
	// add content_length
	if (uwsgi_response_add_content_length(wsgi_req, st.st_size))
		goto end;
	// add last-modified
	if (uwsgi_response_add_last_modified(wsgi_req, st.st_mtime))
		goto end;
	// add mime_type
	size_t mime_type_len = 0;
	char *mime_type = uwsgi_get_mime_type(filename, filename_len, &mime_type_len);
	if (mime_type) {
		if (uwsgi_response_add_content_type(wsgi_req, mime_type, mime_type_len))
			goto end;
	}
	// add ETag (based on file mtime, not rock-solid, but good enough)
	char *etag = uwsgi_num2str(st.st_mtime);
	if (uwsgi_response_add_header(wsgi_req, "ETag", 4, etag, strlen(etag))) {
		free(etag);
		goto end;
	}
	free(etag);
	// start sending the file (note: we do not use sendfile() api, for being able to use caching and transformations)
	if (!send_body)
		goto end;
	// use a pretty big buffer (for performance reasons)
	char buf[32768];
	size_t remains = st.st_size;
	while (remains > 0) {
		ssize_t rlen = read(fd, buf, UMIN(32768, remains));
		if (rlen <= 0) {
			uwsgi_error("uwsgi_wevdav_manage_get/read()");
			break;
		}
		remains -= rlen;
		if (uwsgi_response_write_body_do(wsgi_req, buf, rlen)) {
			break;
		}
	}
end:
	close(fd);
	return UWSGI_OK;
}
예제 #17
0
ssize_t uwsgi_lf_status(struct wsgi_request *wsgi_req, char **buf) {
	*buf = uwsgi_num2str(wsgi_req->status);
	return strlen(*buf);
}
예제 #18
0
파일: emperor.c 프로젝트: arteme/uwsgi
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) {

	struct uwsgi_instance *c_ui = ui;
	struct uwsgi_instance *n_ui = NULL;
	pid_t pid;
	char **vassal_argv;
	char *uef;
	char **uenvs;
	int counter;
	char *colon = NULL;
	int i;
	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\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_malloc(sizeof(struct uwsgi_instance));
	memset(n_ui, 0, 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;

	if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe)) {
		uwsgi_error("socketpair()");
		goto clear;
	}

	event_queue_add_fd_read(uwsgi.emperor_queue, n_ui->pipe[0]);

	if (n_ui->use_config) {
		if (socketpair(AF_UNIX, SOCK_STREAM, 0, n_ui->pipe_config)) {
			uwsgi_error("socketpair()");
			goto clear;
		}
	}

	// TODO pre-start hook

	// a new uWSGI instance will start 
	pid = fork();
	if (pid < 0) {
		uwsgi_error("fork()")
	}
	else if (pid > 0) {
		n_ui->pid = pid;
		// close the right side of the pipe
		close(n_ui->pipe[1]);
		if (n_ui->use_config) {
			close(n_ui->pipe_config[1]);
		}

		if (n_ui->use_config) {
			if (write(n_ui->pipe_config[0], n_ui->config, n_ui->config_len) <= 0) {
				uwsgi_error("write()");
			}
			close(n_ui->pipe_config[0]);
		}
		return;
	}
	else {

		if (uwsgi.emperor_tyrant) {
			uwsgi_log("[emperor-tyrant] dropping privileges to %d %d for instance %s\n", (int) uid, (int) gid, name);
			if (setgid(gid)) {
				uwsgi_error("setgid()");
				exit(1);
			}
			if (setgroups(0, NULL)) {
				uwsgi_error("setgroups()");
				exit(1);
			}

			if (setuid(uid)) {
				uwsgi_error("setuid()");
				exit(1);
			}

		}

		unsetenv("UWSGI_RELOADS");
		unsetenv("NOTIFY_SOCKET");

		uef = uwsgi_num2str(n_ui->pipe[1]);
		if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
			uwsgi_error("setenv()");
			exit(1);
		}
		free(uef);

		if (n_ui->use_config) {
			uef = uwsgi_num2str(n_ui->pipe_config[1]);
			if (setenv("UWSGI_EMPEROR_FD_CONFIG", uef, 1)) {
				uwsgi_error("setenv()");
				exit(1);
			}
			free(uef);
		}

		uenvs = environ;
		while (*uenvs) {
			if (!strncmp(*uenvs, "UWSGI_VASSAL_", 13)) {
				char *ne = uwsgi_concat2("UWSGI_", *uenvs + 13);
				char *oe = uwsgi_concat2n(*uenvs, strchr(*uenvs, '=') - *uenvs, "", 0);
				if (unsetenv(oe)) {
					uwsgi_error("unsetenv()");
					break;
				}
				free(oe);
#ifdef UWSGI_DEBUG
				uwsgi_log("putenv %s\n", ne);
#endif

				if (putenv(ne)) {
					uwsgi_error("putenv()");
				}
				// do not free ne as putenv will add it to the environ
				uenvs = environ;
				continue;
			}
			uenvs++;
		}

		// close the left side of the pipe
		close(n_ui->pipe[0]);

		if (n_ui->use_config) {
			close(n_ui->pipe_config[0]);
		}

		counter = 4;
		struct uwsgi_string_list *uct = uwsgi.vassals_templates;
		while (uct) {
			counter += 2;
			uct = uct->next;
		}

		vassal_argv = uwsgi_malloc(sizeof(char *) * counter);
		// set args
		vassal_argv[0] = uwsgi.binary_path;

		if (uwsgi.emperor_broodlord) {
			colon = strchr(name, ':');
			if (colon) {
				colon[0] = 0;
			}
		}
		// initialize to a default value
		vassal_argv[1] = "--inherit";

		if (!strcmp(name + (strlen(name) - 4), ".xml"))
			vassal_argv[1] = "--xml";
		if (!strcmp(name + (strlen(name) - 4), ".ini"))
			vassal_argv[1] = "--ini";
		if (!strcmp(name + (strlen(name) - 4), ".yml"))
			vassal_argv[1] = "--yaml";
		if (!strcmp(name + (strlen(name) - 5), ".yaml"))
			vassal_argv[1] = "--yaml";
		if (!strcmp(name + (strlen(name) - 3), ".js"))
			vassal_argv[1] = "--json";
		if (!strcmp(name + (strlen(name) - 5), ".json"))
			vassal_argv[1] = "--json";

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


		vassal_argv[2] = name;
		if (uwsgi.emperor_magic_exec) {
			if (!access(name, R_OK | X_OK)) {
				vassal_argv[2] = uwsgi_concat2("exec://", name);
			}

		}

		if (n_ui->use_config) {
			vassal_argv[2] = uwsgi_concat2("emperor://", name);
		}

		counter = 3;
		uct = uwsgi.vassals_templates;
		while (uct) {
			vassal_argv[counter] = "--inherit";
			vassal_argv[counter + 1] = uct->value;
			counter += 2;
			uct = uct->next;
		}
		vassal_argv[counter] = NULL;

		// disable stdin
		int stdin_fd = open("/dev/null", O_RDONLY);
		if (stdin_fd < 0) {
			uwsgi_error_open("/dev/null");
			exit(1);
		}
		if (stdin_fd != 0) {
			if (dup2(stdin_fd, 0)) {
				uwsgi_error("dup2()");
				exit(1);
			}
			close(stdin_fd);
		}

		// close all of the unneded fd
		for (i = 3; i < (int) uwsgi.max_fd; i++) {
			if (n_ui->use_config) {
				if (i == n_ui->pipe_config[1])
					continue;
			}
			if (i != n_ui->pipe[1]) {
				close(i);
			}
		}

		if (uwsgi.vassals_start_hook) {
			uwsgi_log("[emperor] running vassal start-hook: %s %s\n", uwsgi.vassals_start_hook, n_ui->name);
			if (uwsgi.emperor_absolute_dir) {
				if (setenv("UWSGI_VASSALS_DIR", uwsgi.emperor_absolute_dir, 1)) {
					uwsgi_error("setenv()");
				}
			}
			int start_hook_ret = uwsgi_run_command_and_wait(uwsgi.vassals_start_hook, n_ui->name);
			uwsgi_log("[emperor] %s start-hook returned %d\n", n_ui->name, start_hook_ret);
		}

		// start !!!
		if (execvp(vassal_argv[0], vassal_argv)) {
			uwsgi_error("execvp()");
		}
		uwsgi_log("[emperor] is the uwsgi binary in your system PATH ?\n");
		// never here
		exit(UWSGI_EXILE_CODE);
	}

clear:

	free(n_ui);
	c_ui->ui_next = NULL;

}
예제 #19
0
ssize_t uwsgi_lf_epoch(struct wsgi_request *wsgi_req, char **buf) {
        *buf = uwsgi_num2str(uwsgi_now());
        return strlen(*buf);
}