void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) {

	uwsgi_opt_load_ini(opt, value, NULL);

	if (value[0] != '/') {
		up.paste = uwsgi_concat4("config:", uwsgi.cwd, "/", value);
	}
	else {
		up.paste = uwsgi_concat2("config:", value);
        }

	if (!strcmp("ini-paste-logged", opt)) {
		up.paste_logger = 1;
	}
	
}
Example #2
0
File: webdav.c Project: JuanS/uwsgi
static int uwsgi_webdav_prop_del(char *filename, char *attr, char *ns) {
        int ret = 0;
#if defined(__linux__) || defined(__APPLE__)
        char *xattr_name = NULL;
        if (ns) {
                xattr_name = uwsgi_concat4("user.uwsgi.webdav.", ns, "|", attr);
        }
        else {
                xattr_name = uwsgi_concat2("user.uwsgi.webdav.", attr);
        }
#if defined(__linux__)
        ret = removexattr(filename, xattr_name);
#elif defined(__APPLE__)
        ret = removexattr(filename, xattr_name, 0);
#endif
        free(xattr_name);
#endif
        return ret;
}
Example #3
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);
			}
		}

		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]);
	}

	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; 
}
char *uwsgi_format_airbrake_backtrace(struct uwsgi_thread *ut) {

	struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;

	xmlChar *xmlbuff;
	int buffersize;
	xmlDocPtr doc = NULL;
	xmlNodePtr notice_node = NULL, node = NULL, line_node = NULL, errnode = NULL;
	char *msg = NULL;

	doc = xmlNewDoc(BAD_CAST "1.0");
	notice_node = xmlNewNode(NULL, BAD_CAST "notice");
	xmlNewProp(notice_node, BAD_CAST "version", BAD_CAST "2.3");
	xmlDocSetRootElement(doc, notice_node);

	xmlNewChild(notice_node, NULL, BAD_CAST "api-key", BAD_CAST uacc->apikey);

	node = xmlNewChild(notice_node, NULL, BAD_CAST "notifier", NULL);
	xmlNewChild(node, NULL, BAD_CAST "name", BAD_CAST "uWSGI");
	xmlNewChild(node, NULL, BAD_CAST "version", BAD_CAST UWSGI_VERSION);
	xmlNewChild(node, NULL, BAD_CAST "url", BAD_CAST "https://github.com/unbit/uwsgi");

	// request env
	node = xmlNewChild(notice_node, NULL, BAD_CAST "request", NULL);
	node = xmlNewChild(node, NULL, BAD_CAST "cgi-data", NULL);

	line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST UWSGI_VERSION);
	xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "uwsgi_version");

	line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST __VERSION__);
	xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "compiled_with_version");

	struct utsname uuts;
#ifdef __sun__
	if (uname(&uuts) < 0) {
#else
	if (uname(&uuts)) {
#endif
		uwsgi_error("uname()");
	}
	else {
		line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.sysname);
		xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_sysname");

		char *os_version = uwsgi_concat3(uuts.release, "-", uuts.version);
		line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST os_version);
		xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "os_version");
		free(os_version);

		line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.machine);
		xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "machine");

		line_node = xmlNewChild(node, NULL, BAD_CAST "var", BAD_CAST uuts.nodename);
		xmlNewProp(line_node, BAD_CAST "key", BAD_CAST "nodename");

	}
	// end request env

	node = xmlNewChild(notice_node, NULL, BAD_CAST "server-environment", NULL);
	xmlNewChild(node, NULL, BAD_CAST "app-version", BAD_CAST UWSGI_VERSION);
	if (uacc->env) {
		xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST uacc->env);
	}
	else {
		xmlNewChild(node, NULL, BAD_CAST "environment-name", BAD_CAST UWSGI_VERSION);
	}

	errnode = xmlNewChild(notice_node, NULL, BAD_CAST "error", NULL);
	xmlNewChild(errnode, NULL, BAD_CAST "class", BAD_CAST "RuntimeError");
	node = xmlNewChild(errnode, NULL, BAD_CAST "backtrace", NULL);

	char *ctx = NULL;
	char *text = uwsgi_str(ut->buf);
	char *p = strtok_r(text, "\n", &ctx);
	while (p) {
		// skip log messages
		if (!uwsgi_startswith(p, "***", 3))
			goto next;
		// backtrace line looks like this: uwsgi(simple_loop_run+0xc5) [0x451555]
		// we take binary/lib as filename
		// and extract method name from remaining string
		char *n = strchr(p, '(');
		if (n) {
			*n = 0;

			char *pls = strchr(n+1, '+');
			if (pls) {
				*pls = 0;
			}

			if (!strcmp("uwsgi_backtrace", n+1) || !strcmp("what_i_am_doing", n+1)) {
				goto next;
			}
			else if (!strcmp("uwsgi_fpe", n+1)) {
				msg = uwsgi_concat4("uWSGI FPE at ", n+1, " in ", p);
				goto next;
			}

			if (!msg) {
				if (strlen(n+1)) {
					msg = uwsgi_concat4("uWSGI segfault at ", n+1, " in ", p);
				}
				else {
					// method name might be missing
					msg = uwsgi_concat2("uWSGI segfault in ", p);
				}
			}

			// skip empty lines
			if (!p)
				goto next;

			line_node = xmlNewChild(node, NULL, BAD_CAST "line", NULL);

			if ((n+1)[0] == ')') {
				xmlNewProp(line_node, BAD_CAST "method", BAD_CAST "()");
			}
			else {
				xmlNewProp(line_node, BAD_CAST "method", BAD_CAST n+1);
			}

			xmlNewProp(line_node, BAD_CAST "file", BAD_CAST p);

			//xmlNewProp(line_node, BAD_CAST "number", BAD_CAST "0");
		}
next:
		p = strtok_r(NULL, "\n", &ctx);
	}

	xmlNewChild(errnode, NULL, BAD_CAST "message", BAD_CAST msg);

	xmlDocDumpFormatMemory(doc, &xmlbuff, &buffersize, 1);

	xmlFreeDoc(doc);
	xmlCleanupParser();
	xmlMemoryDump();
	free(msg);
	free(text);

	return (char *) xmlbuff;
}


static void uwsgi_airbrake_loop(struct uwsgi_thread *ut) {
	int interesting_fd;
	ut->buf = uwsgi_malloc(uwsgi.log_master_bufsize);

	CURL *curl = curl_easy_init();
	// ARGH !!!
	if (!curl) return;

	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
	curl_easy_setopt(curl, CURLOPT_TIMEOUT, uwsgi.shared->options[UWSGI_OPTION_SOCKET_TIMEOUT]);
	curl_easy_setopt(curl, CURLOPT_READFUNCTION, NULL);
	curl_easy_setopt(curl, CURLOPT_READDATA, ut);
	curl_easy_setopt(curl, CURLOPT_POST, 1L);
	struct curl_slist *expect = NULL; expect = curl_slist_append(expect, "Expect:");
	curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);

	struct uwsgi_airbrake_config *uacc = (struct uwsgi_airbrake_config *) ut->data;
	char *opts = uwsgi_str(uacc->arg);

	// fill curl options
	char *ctx = NULL;
	char *p = strtok_r(opts, ";", &ctx);
	while(p) {
		uwsgi_airbrake_setopt(curl, uwsgi_str(p), uacc);
		p = strtok_r(NULL, ";", &ctx);
	}

	for(;;) {
		int ret = event_queue_wait(ut->queue, -1, &interesting_fd);
		if (ret < 0) return;
		if (ret == 0) continue;
		if (interesting_fd != ut->pipe[1]) continue;
		ssize_t rlen = read(ut->pipe[1], ut->buf, uwsgi.log_master_bufsize);
		if (rlen <= 0) continue;
		ut->pos = 0;
		ut->len = (size_t) rlen;
		ut->custom0 = 0;

		char *notice = uwsgi_format_airbrake_backtrace(ut);

		curl_slist_append(expect, "Accept: */*");
		curl_slist_append(expect, "Content-Type: text/xml; charset=utf-8");
		curl_easy_setopt(curl, CURLOPT_HTTPHEADER, expect);
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, notice);
		curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, strlen(notice));

		curl_easy_setopt(curl, CURLOPT_INFILESIZE_LARGE, (curl_off_t) ut->len);
		CURLcode res = curl_easy_perform(curl);
		if (res != CURLE_OK) {
			uwsgi_log_alarm("-curl] curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
		}
		free(notice);
	}
}
Example #5
0
File: emperor.c Project: ahua/c
static char *emperor_check_on_demand_socket(char *filename) {
	size_t len = 0;
	if (uwsgi.emperor_on_demand_extension) {
		char *tmp = uwsgi_concat2(filename, uwsgi.emperor_on_demand_extension);
		int fd = open(tmp, O_RDONLY);
		free(tmp);
		if (fd < 0) return NULL;
		char *ret = uwsgi_read_fd(fd, &len, 1);
		close(fd);
		// change the first non prinabel character to 0
		size_t i;
		for(i=0;i<len;i++) {
			if (ret[i] < 32) {
				ret[i] = 0;
				break;
			}
		}
		if (ret[0] == 0) {
			free(ret);
			return NULL;
		}
		return ret;
	}
	else if (uwsgi.emperor_on_demand_directory) {
		// we need to build the socket path automagically
		char *start_of_vassal_name = uwsgi_get_last_char(filename, '/');
		if (!start_of_vassal_name) {
			start_of_vassal_name = filename;
		}
		else {
			start_of_vassal_name++;
		}
		char *last_dot = uwsgi_get_last_char(filename, '.');
		if (!last_dot) return NULL;

		return uwsgi_concat4n(uwsgi.emperor_on_demand_directory, strlen(uwsgi.emperor_on_demand_directory), "/", 1, start_of_vassal_name, last_dot - start_of_vassal_name, ".socket", 7);
	}
	else if (uwsgi.emperor_on_demand_exec) {
		int cpipe[2];
                if (pipe(cpipe)) {
                        uwsgi_error("emperor_check_on_demand_socket()pipe()");
			return NULL;
                }
		char *cmd = uwsgi_concat4(uwsgi.emperor_on_demand_exec, " \"", filename, "\"");
                int r = uwsgi_run_command(cmd, NULL, cpipe[1]);
		free(cmd);
		if (r < 0) {
                	close(cpipe[0]);
                	close(cpipe[1]);
			return NULL;
		}
                char *ret = uwsgi_read_fd(cpipe[0], &len, 1);
                close(cpipe[0]);
                close(cpipe[1]);
		// change the first non prinabel character to 0
                size_t i;
                for(i=0;i<len;i++) {
                        if (ret[i] < 32) {
                                ret[i] = 0;
                                break;
                        }
                }
		if (ret[0] == 0) {
			free(ret);
			return NULL;
		}
		return ret;
	}
	return NULL;
}
Example #6
0
void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {

	socklen_t socket_type_len;
	union uwsgi_sockaddr_ptr gsa, isa;
	union uwsgi_sockaddr usa;
	int abstract = 0;

	socket_type_len = sizeof(struct sockaddr_un);
	gsa.sa = &usa.sa;
	if (!getsockname(fd, gsa.sa, &socket_type_len)) {
		if (socket_type_len <= 2) {
			// unbound socket
			return;
		}
		if (gsa.sa->sa_family == AF_UNIX) {
			if (usa.sa_un.sun_path[0] == 0)
				abstract = 1;
			// is it a zerg ?
			if (uwsgi_sock->name == NULL) {
				uwsgi_sock->fd = fd;
				uwsgi_sock->family = AF_UNIX;
				uwsgi_sock->bound = 1;
				uwsgi_sock->name = uwsgi_concat2(usa.sa_un.sun_path + abstract, "");
				if (uwsgi.zerg) {
					uwsgi_log("uwsgi zerg socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path + abstract, uwsgi_sock->fd);
				}
				else {
					uwsgi_log("uwsgi socket %d attached to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), usa.sa_un.sun_path + abstract, uwsgi_sock->fd);
				}
				return;
			}
			if (!uwsgi_startswith(uwsgi_sock->name, "fd://", 5)) {
				if (atoi(uwsgi_sock->name + 5) == fd) {
					uwsgi_sock->fd = fd;
					uwsgi_sock->family = AF_UNIX;
					uwsgi_sock->bound = 1;
					uwsgi_sock->name = uwsgi_str(usa.sa_un.sun_path + abstract);
					uwsgi_log("uwsgi socket %d inherited UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
				}
			}
			else if (!strcmp(usa.sa_un.sun_path + abstract, uwsgi_sock->name + abstract)) {
				uwsgi_sock->fd = fd;
				uwsgi_sock->family = AF_UNIX;
				uwsgi_sock->bound = 1;
				uwsgi_log("uwsgi socket %d inherited UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
			}
		}
		else if (gsa.sa->sa_family == AF_INET) {
			char *computed_addr;
			char computed_port[6];
			isa.sa_in = (struct sockaddr_in *) &usa;
			char ipv4a[INET_ADDRSTRLEN + 1];
			memset(ipv4a, 0, INET_ADDRSTRLEN + 1);
			memset(computed_port, 0, 6);


			if (snprintf(computed_port, 6, "%d", ntohs(isa.sa_in->sin_port)) > 0) {
				if (inet_ntop(AF_INET, (const void *) &isa.sa_in->sin_addr.s_addr, ipv4a, INET_ADDRSTRLEN)) {

					if (!strcmp("0.0.0.0", ipv4a)) {
						computed_addr = uwsgi_concat2(":", computed_port);
					}
					else {
						computed_addr = uwsgi_concat3(ipv4a, ":", computed_port);
					}

					// is it a zerg ?
					if (uwsgi_sock->name == NULL) {
						uwsgi_sock->fd = fd;
						uwsgi_sock->family = AF_INET;
						uwsgi_sock->bound = 1;
						uwsgi_sock->name = uwsgi_concat2(computed_addr, "");
						if (uwsgi.zerg) {
							uwsgi_log("uwsgi zerg socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd);
						}
						else {
							uwsgi_log("uwsgi socket %d attached to INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd);
						}
						free(computed_addr);
						return;
					}
					char *asterisk = strchr(uwsgi_sock->name, '*');
					int match = 1;
					if (asterisk) {
						asterisk[0] = 0;
						match = strncmp(computed_addr, uwsgi_sock->name, strlen(uwsgi_sock->name));
						asterisk[0] = '*';
					}
					else {
						if (!uwsgi_startswith(uwsgi_sock->name, "fd://", 5)) {
							if (atoi(uwsgi_sock->name + 5) == fd) {
								uwsgi_sock->fd = fd;
								uwsgi_sock->family = AF_INET;
								uwsgi_sock->bound = 1;
								uwsgi_sock->name = uwsgi_str(computed_addr);
								uwsgi_log("uwsgi socket %d inherited INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
								match = 1;
							}
						}
						else {
							match = strcmp(computed_addr, uwsgi_sock->name);
						}
					}
					if (!match) {
						uwsgi_sock->fd = fd;
						uwsgi_sock->family = AF_INET;
						uwsgi_sock->bound = 1;
						uwsgi_log("uwsgi socket %d inherited INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
					}
					free(computed_addr);
				}
			}
		}
#ifdef UWSGI_IPV6
		else if (gsa.sa->sa_family == AF_INET6) {
			char *computed_addr;
			char computed_port[6];
			isa.sa_in6 = (struct sockaddr_in6 *) &usa;
			char ipv6a[INET6_ADDRSTRLEN + 1];
			memset(ipv6a, 0, INET_ADDRSTRLEN + 1);
			memset(computed_port, 0, 6);
			int match = 0;


			if (snprintf(computed_port, 6, "%d", ntohs(isa.sa_in6->sin6_port)) > 0) {
				if (inet_ntop(AF_INET6, (const void *) &isa.sa_in6->sin6_addr.s6_addr, ipv6a, INET6_ADDRSTRLEN)) {
					uwsgi_log("ipv6a = %s\n", ipv6a);
					if (!strcmp("::", ipv6a)) {
						computed_addr = uwsgi_concat2("[::]:", computed_port);
					}
					else {
						computed_addr = uwsgi_concat4("[", ipv6a, "]:", computed_port);
					}
					// is it a zerg ?
					if (uwsgi_sock->name == NULL) {
						uwsgi_sock->fd = fd;
						uwsgi_sock->family = AF_INET6;
						uwsgi_sock->bound = 1;
						uwsgi_sock->name = uwsgi_concat2(computed_addr, "");
						if (uwsgi.zerg) {
							uwsgi_log("uwsgi zerg socket %d attached to INET6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd);
						}
						else {
							uwsgi_log("uwsgi socket %d attached to INET6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), computed_addr, uwsgi_sock->fd);
						}
						free(computed_addr);
						return;
					}

					if (!uwsgi_startswith(uwsgi_sock->name, "fd://", 5)) {
						if (atoi(uwsgi_sock->name + 5) == fd) {
							uwsgi_sock->fd = fd;
							uwsgi_sock->family = AF_INET6;
							uwsgi_sock->bound = 1;
							uwsgi_sock->name = uwsgi_str(computed_addr);
							uwsgi_log("uwsgi socket %d inherited INET address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
							match = 1;
						}
					}
					else {
						match = strcmp(computed_addr, uwsgi_sock->name);
					}

					if (!match) {
						uwsgi_sock->fd = fd;
						uwsgi_sock->family = AF_INET;
						uwsgi_sock->bound = 1;
						uwsgi_log("uwsgi socket %d inherited INET6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
					}
					free(computed_addr);
				}
			}
		}

#endif
	}

}