예제 #1
0
static int uwsgi_hook_writefifo(char *arg) {
	char *space = strchr(arg, ' ');
	if (!space) {
		uwsgi_log("invalid hook writefifo syntax, must be: <file> <string>\n");
		return -1;
	}
	*space = 0;
	int fd = open(arg, O_WRONLY|O_NONBLOCK);
	if (fd < 0) {
		uwsgi_error_open(arg);
		*space = ' ';
		if (errno == ENODEV) return 0;
#ifdef ENXIO
		if (errno == ENXIO) return 0;
#endif
		return -1;
	}
	*space = ' ';
	size_t l = strlen(space+1);
	if (write(fd, space+1, l) != (ssize_t) l) {
		uwsgi_error("uwsgi_hook_writefifo()/write()");
		close(fd);
		return -1;
	}
	close(fd);
        return 0;
}
예제 #2
0
static int uwsgi_hook_writen(char *arg) {
        char *space = strchr(arg, ' ');
        if (!space) {
                uwsgi_log("invalid hook writen syntax, must be: <file> <string>\n");
                return -1;
        }
        *space = 0;
        int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
        if (fd < 0) {
                uwsgi_error_open(arg);
                *space = ' ';
                return -1;
        }
        *space = ' ';
        size_t l = strlen(space+1);
	char *buf = uwsgi_malloc(l + 1);
	memcpy(buf, space+1, l);
	buf[l] = '\n';
        if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
                uwsgi_error("uwsgi_hook_writen()/write()");
		free(buf);
                close(fd);
                return -1;
        }
	free(buf);
        close(fd);
        return 0;
}
예제 #3
0
파일: daemons.c 프로젝트: xwssole/uwsgi
int uwsgi_check_pidfile(char *filename) {
	struct stat st;
	pid_t ret = -1;
	int fd = open(filename, O_RDONLY);
	if (fd < 0) {
		uwsgi_error_open(filename);
		goto end;
	}
	if (fstat(fd, &st)) {
		uwsgi_error("fstat()");
		goto end2;
	}
	char *pidstr = uwsgi_calloc(st.st_size + 1);
	if (read(fd, pidstr, st.st_size) != st.st_size) {
		uwsgi_error("read()");
		goto end3;
	}
	pid_t pid = atoi(pidstr);
	if (pid <= 0)
		goto end3;
	if (!kill(pid, 0)) {
		ret = pid;
	}
end3:
	free(pidstr);
end2:
	close(fd);
end:
	return ret;
}
예제 #4
0
static int u_offload_sendfile_prepare(struct wsgi_request *wsgi_req, struct uwsgi_offload_request *uor) {

	if (!uor->name && uor->fd == -1) return -1;

	if (uor->name) {
		uor->fd = open(uor->name, O_RDONLY | O_NONBLOCK);
		if (uor->fd < 0) {
			uwsgi_error_open(uor->name);
			return -1;
		}
	}

	// make a fstat to get the file size
	if (!uor->len) {
		struct stat st;
		if (fstat(uor->fd, &st)) {
			uwsgi_error("u_offload_sendfile_prepare()/fstat()");
			if (uor->name) {
				close(uor->fd);
			}
			return -1;
		}
		uor->len = st.st_size;
	}

	if (uor->fd2 == -1) {
		uor->fd2 = uor->s;
	}
	uor->s = -1;

	return 0;
}
예제 #5
0
static int uwsgi_hook_creat(char *arg) {
        int fd = open(arg, O_WRONLY|O_CREAT|O_TRUNC, 0666);
        if (fd < 0) {
                uwsgi_error_open(arg);
                return -1;
        }
        close(fd);
        return 0;
}
예제 #6
0
void uwsgi_python_hijack(void) {

	// the pyshell will be execute only in the first worker

#ifndef UWSGI_PYPY
	FILE *pyfile;
	if (up.pyrun) {
		uwsgi.workers[uwsgi.mywid].hijacked = 1;
		UWSGI_GET_GIL;
		pyfile = fopen(up.pyrun, "r");
		if (!pyfile) {
			uwsgi_error_open(up.pyrun);
			exit(1);
		}
		PyRun_SimpleFile(pyfile, up.pyrun);	
		// could be never executed
		exit(0);
	}
#endif

	if (up.pyshell_oneshot && uwsgi.workers[uwsgi.mywid].hijacked_count > 0) {
		uwsgi.workers[uwsgi.mywid].hijacked = 0;
		return;
	}
	if (up.pyshell && uwsgi.mywid == 1) {
		uwsgi.workers[uwsgi.mywid].hijacked = 1;
		uwsgi.workers[uwsgi.mywid].hijacked_count++;
		// re-map stdin to stdout and stderr if we are logging to a file
		if (uwsgi.logfile) {
			if (dup2(0, 1) < 0) {
				uwsgi_error("dup2()");
			}
			if (dup2(0, 2) < 0) {
				uwsgi_error("dup2()");
			}
		}
		UWSGI_GET_GIL;
		PyImport_ImportModule("readline");

#ifndef UWSGI_PYPY
		int ret = PyRun_InteractiveLoop(stdin, "uwsgi");

		if (up.pyshell_oneshot) {
			exit(UWSGI_DE_HIJACKED_CODE);
		}

		if (ret == 0) {
			exit(UWSGI_QUIET_CODE);
		}
#endif
		exit(0);
	}
}
예제 #7
0
파일: event.c 프로젝트: sashka/uwsgi
int event_queue_add_file_monitor(int eq, char *filename, int *id) {

	struct kevent kev;

	int fd = open(filename, O_RDONLY);
	if (fd < 0) {
		uwsgi_error_open(filename);
		return -1;
	}
	
        EV_SET(&kev, fd, EVFILT_VNODE, EV_ADD|EV_CLEAR, NOTE_WRITE|NOTE_DELETE|NOTE_EXTEND|NOTE_ATTRIB|NOTE_RENAME|NOTE_REVOKE, 0, 0);
        if (kevent(eq, &kev, 1, NULL, 0, NULL) < 0) {
                uwsgi_error("kevent()");
                return -1;
        }

	*id = fd;

	uwsgi_log("added new file to monitor %s\n", filename);
	
	return fd;
}
예제 #8
0
static int uwsgi_hook_append(char *arg) {
        char *space = strchr(arg, ' ');
        if (!space) {
                uwsgi_log("invalid hook append syntax, must be: <file> <string>\n");
                return -1;
        }
        *space = 0;
        int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
        if (fd < 0) {
                uwsgi_error_open(arg);
                *space = ' ';
                return -1;
        }
        *space = ' ';
        size_t l = strlen(space+1);
        if (write(fd, space+1, l) != (ssize_t) l) {
                uwsgi_error("uwsgi_hook_append()/write()");
                close(fd);
                return -1;
        }
        close(fd);
        return 0;
}
예제 #9
0
파일: io.c 프로젝트: tinyserver/uwsgi
// simply read the whole content of a file
char *uwsgi_simple_file_read(char *filename) {

	struct stat sb;
	char *buffer;
	ssize_t len;
	int fd = open(filename, O_RDONLY);
	if (fd < 0) {
		uwsgi_error_open(filename);
		goto end;
	}

	if (fstat(fd, &sb)) {
		uwsgi_error("fstat()");
		close(fd);
		goto end;
	}

	buffer = uwsgi_malloc(sb.st_size + 1);

	len = read(fd, buffer, sb.st_size);
	if (len != sb.st_size) {
		uwsgi_error("read()");
		free(buffer);
		close(fd);
		goto end;
	}

	close(fd);
	if (buffer[sb.st_size - 1] == '\n' || buffer[sb.st_size - 1] == '\r') {
		buffer[sb.st_size - 1] = 0;
	}
	buffer[sb.st_size] = 0;
	return buffer;
end:
	return (char *) "";

}
예제 #10
0
파일: stats.c 프로젝트: arteme/uwsgi
void uwsgi_stats_pusher_file(struct uwsgi_stats_pusher_instance *uspi, char *json, size_t json_len) {
	struct uwsgi_stats_pusher_file_conf *uspic = (struct uwsgi_stats_pusher_file_conf *) uspi->data;
	if (!uspi->configured) {
		uspic = uwsgi_calloc(sizeof(struct uwsgi_stats_pusher_file_conf));
		if (uspi->arg) {
			if (uwsgi_kvlist_parse(uspi->arg, strlen(uspi->arg), ',', '=', "path", &uspic->path, "separator", &uspic->separator, "freq", &uspic->freq, NULL)) {
				free(uspi);
				return;
			}
		}
		if (!uspic->path)
			uspic->path = "uwsgi.stats";
		if (!uspic->separator)
			uspic->separator = "\n\n";
		if (uspic->freq)
			uspi->freq = atoi(uspic->freq);
		uspi->configured = 1;
		uspi->data = uspic;
	}

	int fd = open(uspic->path, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
	if (fd < 0) {
		uwsgi_error_open(uspic->path);
		return;
	}
	ssize_t rlen = write(fd, json, json_len);
	if (rlen != (ssize_t) json_len) {
		uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
	}

	rlen = write(fd, uspic->separator, strlen(uspic->separator));
	if (rlen != (ssize_t) strlen(uspic->separator)) {
		uwsgi_error("uwsgi_stats_pusher_file() -> write()\n");
	}

	close(fd);
}
예제 #11
0
static int uwsgi_hook_appendn(char *arg) {
        char *space = strchr(arg, ' ');
	if (space)
        	*space = 0;
        int fd = open(arg, O_WRONLY|O_CREAT|O_APPEND, 0666);
        if (fd < 0) {
                uwsgi_error_open(arg);
		if (space)
                	*space = ' ';
                return -1;
        }
	if (!space) {
		// simple newline
		if (write(fd, "\n", 1) != 1) {
                	uwsgi_error("uwsgi_hook_appendn()/write()");
			close(fd);
			return -1;
		}
		close(fd);
		return 0;
	}

        *space = ' ';
        size_t l = strlen(space+1);
        char *buf = uwsgi_malloc(l + 1);
	memcpy(buf, space+1, l);
        buf[l] = '\n';
        if (write(fd, buf, l+1) != (ssize_t) (l+1)) {
                uwsgi_error("uwsgi_hook_appendn()/write()");
                free(buf);
                close(fd);
                return -1;
        }
        free(buf);
        close(fd);
        return 0;
}
예제 #12
0
void uwsgi_bind_sockets() {
	socklen_t socket_type_len;
	union uwsgi_sockaddr usa;
	union uwsgi_sockaddr_ptr gsa;

	struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
	while (uwsgi_sock) {
		if (!uwsgi_sock->bound && !uwsgi_socket_is_already_bound(uwsgi_sock->name)) {
			char *tcp_port = strrchr(uwsgi_sock->name, ':');
			if (tcp_port == NULL) {
				uwsgi_sock->fd = bind_to_unix(uwsgi_sock->name, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
				uwsgi_sock->family = AF_UNIX;
				if (uwsgi.chown_socket) {
					uwsgi_chown(uwsgi_sock->name, uwsgi.chown_socket);
				}
				uwsgi_log("uwsgi socket %d bound to UNIX address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
			}
			else {
#ifdef UWSGI_IPV6
				if (uwsgi_sock->name[0] == '[' && tcp_port[-1] == ']') {
					uwsgi_sock->fd = bind_to_tcp6(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
					uwsgi_log("uwsgi socket %d bound to TCP6 address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
					uwsgi_sock->family = AF_INET6;
				}
				else {
#endif
					uwsgi_sock->fd = bind_to_tcp(uwsgi_sock->name, uwsgi.listen_queue, tcp_port);
					uwsgi_log("uwsgi socket %d bound to TCP address %s fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
					uwsgi_sock->family = AF_INET;
#ifdef UWSGI_IPV6
				}
#endif
			}

			if (uwsgi_sock->fd < 0 && !uwsgi_sock->per_core) {
				uwsgi_log("unable to create server socket on: %s\n", uwsgi_sock->name);
				exit(1);
			}
		}
		uwsgi_sock->bound = 1;
		uwsgi_sock = uwsgi_sock->next;
	}


	if (uwsgi.chown_socket) {
		if (!uwsgi.master_as_root) {
			uwsgi_as_root();
		}
	}

	int zero_used = 0;
	uwsgi_sock = uwsgi.sockets;
	while (uwsgi_sock) {
		if (uwsgi_sock->bound && uwsgi_sock->fd == 0) {
			zero_used = 1;
			break;
		}
		uwsgi_sock = uwsgi_sock->next;
	}

	if (!zero_used) {
		socket_type_len = sizeof(struct sockaddr_un);
		gsa.sa = (struct sockaddr *) &usa;
		if (!uwsgi.skip_zero && !getsockname(0, gsa.sa, &socket_type_len)) {
			if (gsa.sa->sa_family == AF_UNIX) {
				uwsgi_sock = uwsgi_new_socket(uwsgi_getsockname(0));
				uwsgi_sock->family = AF_UNIX;
				uwsgi_sock->fd = 0;
				uwsgi_sock->bound = 1;
				uwsgi_log("uwsgi socket %d inherited UNIX address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
			}
			else {
				uwsgi_sock = uwsgi_new_socket(uwsgi_getsockname(0));
				uwsgi_sock->family = AF_INET;
				uwsgi_sock->fd = 0;
				uwsgi_sock->bound = 1;
				uwsgi_log("uwsgi socket %d inherited INET address %s fd 0\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name);
			}
		}
		else if (!uwsgi.honour_stdin) {
			int fd = open("/dev/null", O_RDONLY);
			if (fd < 0) {
				uwsgi_error_open("/dev/null");
				exit(1);
			}
			if (fd != 0) {
				if (dup2(fd, 0) < 0) {
					uwsgi_error("dup2()");
					exit(1);
				}
				close(fd);
			}
		}
		else if (uwsgi.honour_stdin) {
			if (!tcgetattr(0, &uwsgi.termios)) {
				uwsgi.restore_tc = 1;
			}
		}

	}

	// check for auto_port socket
	uwsgi_sock = uwsgi.sockets;
	while (uwsgi_sock) {
		if (uwsgi_sock->auto_port) {
#ifdef UWSGI_IPV6
			if (uwsgi_sock->family == AF_INET6) {
				uwsgi_log("uwsgi socket %d bound to TCP6 address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
			}
			else {
#endif
				uwsgi_log("uwsgi socket %d bound to TCP address %s (port auto-assigned) fd %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi_sock->fd);
#ifdef UWSGI_IPV6
			}
#endif
		}
		uwsgi_sock = uwsgi_sock->next;
	}


}
예제 #13
0
void uwsgi_map_sockets() {
	struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
	while (uwsgi_sock) {
		struct uwsgi_string_list *usl = uwsgi.map_socket;
		int enabled = 1;
		while (usl) {

			char *colon = strchr(usl->value, ':');
			if (!colon) {
				uwsgi_log("invalid socket mapping, must be socket:worker[,worker...]\n");
				exit(1);
			}
			if ((int) uwsgi_str_num(usl->value, colon - usl->value) == uwsgi_get_socket_num(uwsgi_sock)) {
				enabled = 0;
				char *p = strtok(colon + 1, ",");
				while (p != NULL) {
					int w = atoi(p);
					if (w < 1 || w > uwsgi.numproc) {
						uwsgi_log("invalid worker num: %d\n", w);
						exit(1);
					}
					if (w == uwsgi.mywid) {
						enabled = 1;
						uwsgi_log("mapped socket %d (%s) to worker %d\n", uwsgi_get_socket_num(uwsgi_sock), uwsgi_sock->name, uwsgi.mywid);
						break;
					}
					p = strtok(NULL, ",");
				}
			}

			usl = usl->next;
		}

		if (!enabled) {
			close(uwsgi_sock->fd);
			int fd = open("/dev/null", O_RDONLY);
			if (fd < 0) {
				uwsgi_error_open("/dev/null");
				exit(1);
			}
			if (fd != uwsgi_sock->fd) {
				if (dup2(fd, uwsgi_sock->fd) < 0) {
					uwsgi_error("dup2()");
					exit(1);
				}
				close(fd);
			}
			uwsgi_sock->disabled = 1;
		}


		uwsgi_sock = uwsgi_sock->next;

	}

	uwsgi_sock = uwsgi.sockets;
	while (uwsgi_sock) {
		if (uwsgi_sock->disabled) {
			uwsgi_sock = uwsgi_del_socket(uwsgi_sock);
		}
		else {
			uwsgi_sock = uwsgi_sock->next;
		}
	}

}
예제 #14
0
/*
CHANGED in 2.0.7: wsgi_req is useless !
*/
char *uwsgi_spool_request(struct wsgi_request *wsgi_req, char *buf, size_t len, char *body, size_t body_len) {

	struct timeval tv;
	static uint64_t internal_counter = 0;
	int fd = -1;
	struct spooler_req sr;

	if (len > 0xffff) {
		uwsgi_log("[uwsgi-spooler] args buffer is limited to 64k, use the 'body' for bigger values\n");
		return NULL;
	}

	// parse the request buffer
	memset(&sr, 0, sizeof(struct spooler_req));
	uwsgi_hooked_parse(buf, len, spooler_req_parser_hook, &sr);
	
	struct uwsgi_spooler *uspool = uwsgi.spoolers;
	if (!uspool) {
		uwsgi_log("[uwsgi-spooler] no spooler available\n");
		return NULL;
	}

	// if it is a number, get the spooler by id instead of by name
	if (sr.spooler && sr.spooler_len) {
		uspool = uwsgi_get_spooler_by_name(sr.spooler, sr.spooler_len);
		if (!uspool) {
			uwsgi_log("[uwsgi-spooler] unable to find spooler \"%.*s\"\n", sr.spooler_len, sr.spooler);
			return NULL;
		}
	}

	// this lock is for threads, the pid value in filename will avoid multiprocess races
	uwsgi_lock(uspool->lock);

	// we increase it even if the request fails
	internal_counter++;

	gettimeofday(&tv, NULL);

	char *filename = NULL;
	size_t filename_len = 0;

	if (sr.priority && sr.priority_len) {
		filename_len = strlen(uspool->dir) + sr.priority_len + strlen(uwsgi.hostname) + 256;	
		filename = uwsgi_malloc(filename_len);
		int ret = snprintf(filename, filename_len, "%s/%.*s", uspool->dir, (int) sr.priority_len, sr.priority);
		if (ret <= 0 || ret >= (int) filename_len) {
			uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
			free(filename);
			uwsgi_unlock(uspool->lock);
			return NULL;
		}
		// no need to check for errors...
		(void) mkdir(filename, 0777);

		ret = snprintf(filename, filename_len, "%s/%.*s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, (int)sr.priority_len, sr.priority, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter, rand(),
				(unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
		if (ret <= 0 || ret >=(int)  filename_len) {
                        uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
			free(filename);
			uwsgi_unlock(uspool->lock);
			return NULL;
		}
	}
	else {
		filename_len = strlen(uspool->dir) + strlen(uwsgi.hostname) + 256;
                filename = uwsgi_malloc(filename_len);
		int ret = snprintf(filename, filename_len, "%s/uwsgi_spoolfile_on_%s_%d_%llu_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), (unsigned long long) internal_counter,
				rand(), (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec);
		if (ret <= 0 || ret >= (int) filename_len) {
                        uwsgi_log("[uwsgi-spooler] error generating spooler filename\n");
			free(filename);
			uwsgi_unlock(uspool->lock);
			return NULL;
		}
	}

	fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
	if (fd < 0) {
		uwsgi_error_open(filename);
		free(filename);
		uwsgi_unlock(uspool->lock);
		return NULL;
	}

	// now lock the file, it will no be runnable, until the lock is not removed
	// a race could come if the spooler take the file before fcntl is called
	// in such case the spooler will detect a zeroed file and will retry later
	if (uwsgi_fcntl_lock(fd)) {
		close(fd);
		free(filename);
		uwsgi_unlock(uspool->lock);
		return NULL;
	}

	struct uwsgi_header uh;
	uh.modifier1 = 17;
	uh.modifier2 = 0;
	uh.pktsize = (uint16_t) len;
#ifdef __BIG_ENDIAN__
	uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif

	if (write(fd, &uh, 4) != 4) {
		uwsgi_log("[spooler] unable to write header for %s\n", filename);
		goto clear;
	}

	if (write(fd, buf, len) != (ssize_t) len) {
		uwsgi_log("[spooler] unable to write args for %s\n", filename);
		goto clear;
	}

	if (body && body_len > 0) {
		if ((size_t) write(fd, body, body_len) != body_len) {
			uwsgi_log("[spooler] unable to write body for %s\n", filename);
			goto clear;
		}
	}

	if (sr.at > 0) {
#ifdef __UCLIBC__
		struct timespec ts[2]; 
		ts[0].tv_sec = sr.at; 
		ts[0].tv_nsec = 0;
		ts[1].tv_sec = sr.at;
		ts[1].tv_nsec = 0; 
		if (futimens(fd, ts)) {
			uwsgi_error("uwsgi_spooler_request()/futimens()");	
		}
#else
		struct timeval tv[2];
		tv[0].tv_sec = sr.at;
		tv[0].tv_usec = 0;
		tv[1].tv_sec = sr.at;
		tv[1].tv_usec = 0;
#ifdef __sun__
		if (futimesat(fd, NULL, tv)) {
#else
		if (futimes(fd, tv)) {
#endif
			uwsgi_error("uwsgi_spooler_request()/futimes()");
		}
#endif
	}

	// here the file will be unlocked too
	close(fd);

	if (!uwsgi.spooler_quiet)
		uwsgi_log("[spooler] written %lu bytes to file %s\n", (unsigned long) len + body_len + 4, filename);

	// and here waiting threads can continue
	uwsgi_unlock(uspool->lock);

/*	wake up the spoolers attached to the specified dir ... (HACKY) 
	no need to fear races, as USR1 is harmless an all of the uWSGI processes...
	it could be a problem if a new process takes the old pid, but modern systems should avoid that
*/

	struct uwsgi_spooler *spoolers = uwsgi.spoolers;
	while (spoolers) {
		if (!strcmp(spoolers->dir, uspool->dir)) {
			if (spoolers->pid > 0 && spoolers->running == 0) {
				(void) kill(spoolers->pid, SIGUSR1);
			}
		}
		spoolers = spoolers->next;
	}

	return filename;


clear:
	uwsgi_unlock(uspool->lock);
	uwsgi_error("uwsgi_spool_request()/write()");
	if (unlink(filename)) {
		uwsgi_error("uwsgi_spool_request()/unlink()");
	}
	free(filename);
	// unlock the file too
	close(fd);
	return NULL;
}



void spooler(struct uwsgi_spooler *uspool) {

	// prevent process blindly reading stdin to make mess
	int nullfd;

	// asked by Marco Beri
#ifdef __HAIKU__
#ifdef UWSGI_DEBUG
	uwsgi_log("lowering spooler priority to %d\n", B_LOW_PRIORITY);
#endif
	set_thread_priority(find_thread(NULL), B_LOW_PRIORITY);
#else
#ifdef UWSGI_DEBUG
	uwsgi_log("lowering spooler priority to %d\n", PRIO_MAX);
#endif
	setpriority(PRIO_PROCESS, getpid(), PRIO_MAX);
#endif

	nullfd = open("/dev/null", O_RDONLY);
	if (nullfd < 0) {
		uwsgi_error_open("/dev/null");
		exit(1);
	}

	if (nullfd != 0) {
		dup2(nullfd, 0);
		close(nullfd);
	}

	int spooler_event_queue = event_queue_init();
	int interesting_fd = -1;

	if (uwsgi.master_process) {
		event_queue_add_fd_read(spooler_event_queue, uwsgi.shared->spooler_signal_pipe[1]);
	}

	// reset the tasks counter
	uspool->tasks = 0;

	for (;;) {


		if (chdir(uspool->dir)) {
			uwsgi_error("chdir()");
			exit(1);
		}

		if (uwsgi.spooler_ordered) {
#ifdef __linux__
			spooler_scandir(uspool, NULL);
#else
			spooler_readdir(uspool, NULL);
#endif
		}
		else {
			spooler_readdir(uspool, NULL);
		}

		int timeout = uwsgi.shared->spooler_frequency ? uwsgi.shared->spooler_frequency : uwsgi.spooler_frequency;
		if (wakeup > 0) {
			timeout = 0;
		}

		if (event_queue_wait(spooler_event_queue, timeout, &interesting_fd) > 0) {
			if (uwsgi.master_process) {
				if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
					uwsgi_receive_signal(interesting_fd, "spooler", (int) getpid());
				}
			}
		}

		// avoid races
		uint64_t tmp_wakeup = wakeup;
		if (tmp_wakeup > 0) {
			tmp_wakeup--;
		}
		wakeup = tmp_wakeup;

	}
}
예제 #15
0
파일: io.c 프로젝트: tinyserver/uwsgi
/*
	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;
}
예제 #16
0
파일: progress.c 프로젝트: Algy/uwsgi
char *uwsgi_upload_progress_create(struct wsgi_request *wsgi_req, int *fd) {
	const char *x_progress_id = "X-Progress-ID=";
	char *xpi_ptr = (char *) x_progress_id;
	uint16_t i;
	char *upload_progress_filename = NULL;

	if (wsgi_req->uri_len <= 51)
		return NULL;


	for (i = 0; i < wsgi_req->uri_len; i++) {
		if (wsgi_req->uri[i] == xpi_ptr[0]) {
			if (xpi_ptr[0] == '=') {
				if (wsgi_req->uri + i + 36 <= wsgi_req->uri + wsgi_req->uri_len) {
					upload_progress_filename = wsgi_req->uri + i + 1;
				}
				break;
			}
			xpi_ptr++;
		}
		else {
			xpi_ptr = (char *) x_progress_id;
		}
	}

	// now check for valid uuid (from spec available at http://en.wikipedia.org/wiki/Universally_unique_identifier)
	if (!upload_progress_filename)
		return NULL;

	uwsgi_log("upload progress uuid = %.*s\n", 36, upload_progress_filename);
	if (!check_hex(upload_progress_filename, 8))
		return NULL;
	if (upload_progress_filename[8] != '-')
		return NULL;

	if (!check_hex(upload_progress_filename + 9, 4))
		return NULL;
	if (upload_progress_filename[13] != '-')
		return NULL;

	if (!check_hex(upload_progress_filename + 14, 4))
		return NULL;
	if (upload_progress_filename[18] != '-')
		return NULL;

	if (!check_hex(upload_progress_filename + 19, 4))
		return NULL;
	if (upload_progress_filename[23] != '-')
		return NULL;

	if (!check_hex(upload_progress_filename + 24, 12))
		return NULL;

	upload_progress_filename = uwsgi_concat4n(uwsgi.upload_progress, strlen(uwsgi.upload_progress), "/", 1, upload_progress_filename, 36, ".js", 3);
	// here we use O_EXCL to avoid eventual application bug in uuid generation/using
	*fd = open(upload_progress_filename, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR | S_IRGRP);
	if (*fd < 0) {
		uwsgi_error_open(upload_progress_filename);
		free(upload_progress_filename);
		return NULL;
	}

	return upload_progress_filename;
}
예제 #17
0
파일: mongrel2.c 프로젝트: avar/uwsgi
static int uwsgi_mongrel2_json_parse(json_t * root, struct wsgi_request *wsgi_req) {

	char *json_val;
	char *query_string = NULL;
	size_t query_string_len = 0;
	size_t script_name_len = 0;
	void *json_iter;
	char *json_key;
	json_t *json_value;

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "METHOD"))) {
		if (!strcmp(json_val, "JSON")) {
			return -1;
		}
		wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, json_val, strlen(json_val));
	}

	// pretty easy, we get the file and we map it to wsgi_req->post_file, uWSGI read api will automatically use this
	if ((json_val = uwsgi_mongrel2_json_get_string(root, "x-mongrel2-upload-done"))) {
		wsgi_req->post_file = fopen(json_val, "r");
		if (!wsgi_req->post_file) {
			uwsgi_error_open(json_val);
			return -1;
		}
	}
	else if (uwsgi_mongrel2_json_get_string(root, "x-mongrel2-upload-start")) {
		return -1;
	}


	wsgi_req->uh->pktsize += uwsgi_mongrel2_json_add(wsgi_req, root, "VERSION", "SERVER_PROTOCOL", 15, NULL, NULL);
	wsgi_req->uh->pktsize += uwsgi_mongrel2_json_add(wsgi_req, root, "QUERY", "QUERY_STRING", 12, &query_string, &query_string_len);
	if (query_string == NULL) {
		// always set QUERY_STRING
		wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
	}

	// set SCRIPT_NAME to an empty value
	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0);

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "PATH"))) {
		wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, json_val + script_name_len, strlen(json_val + script_name_len));
		if (query_string_len) {
			char *request_uri = uwsgi_concat3n(json_val, strlen(json_val), "?", 1, query_string, query_string_len);
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, request_uri, strlen(json_val) + 1 + query_string_len);
			free(request_uri);
		}
		else {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, json_val, strlen(json_val));
		}
	}

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "URL_SCHEME"))) {
                wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "UWSGI_SCHEME", 12, json_val, strlen(json_val));
        }

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "host"))) {
		char *colon = strchr(json_val, ':');
		if (colon) {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, strlen(colon + 1));
		}
		else {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
		}
	}

	if ((json_val = uwsgi_mongrel2_json_get_string(root, "x-forwarded-for"))) {
		char *colon = strchr(json_val, ',');
		if (colon) {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - json_val);
		}
		else {
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, json_val, strlen(json_val));
		}
	}


	if ((json_val = uwsgi_mongrel2_json_get_string(root, "content-length"))) {
		wsgi_req->post_cl = atoi(json_val);
	}

	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);

	json_iter = json_object_iter(root);

	while (json_iter) {
		json_key = (char *) json_object_iter_key(json_iter);
		// is it a header ?
		if (json_key[0] >= 97) {
			json_value = json_object_iter_value(json_iter);
			if (json_is_string(json_value)) {
				json_val = (char *) json_string_value(json_value);
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_header(wsgi_req, json_key, strlen(json_key), json_val, strlen(json_val));
			}
		}
		json_iter = json_object_iter_next(root, json_iter);
	}

	return 0;

}
예제 #18
0
파일: spooler.c 프로젝트: smartstudy/uwsgi
int spool_request(struct uwsgi_spooler *uspool, char *filename, int rn, int core_id, char *buffer, int size, char *priority, time_t at, char *body, size_t body_len) {

    struct timeval tv;
    int fd;
    struct uwsgi_header uh;

    if (!uspool) {
        uspool = uwsgi.spoolers;
    }

    // this lock is for threads, the pid value in filename will avoid multiprocess races
    uwsgi_lock(uspool->lock);

    gettimeofday(&tv, NULL);

    if (priority) {
        if (snprintf(filename, 1024, "%s/%s", uspool->dir, priority) <= 0) {
            uwsgi_unlock(uspool->lock);
            return 0;
        }
        // no need to check for errors...
        (void) mkdir(filename, 0777);

        if (snprintf(filename, 1024, "%s/%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, priority, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
            uwsgi_unlock(uspool->lock);
            return 0;
        }
    }
    else {
        if (snprintf(filename, 1024, "%s/uwsgi_spoolfile_on_%s_%d_%d_%d_%llu_%llu", uspool->dir, uwsgi.hostname, (int) getpid(), rn, core_id, (unsigned long long) tv.tv_sec, (unsigned long long) tv.tv_usec) <= 0) {
            uwsgi_unlock(uspool->lock);
            return 0;
        }
    }

    fd = open(filename, O_CREAT | O_EXCL | O_WRONLY, S_IRUSR | S_IWUSR);
    if (fd < 0) {
        uwsgi_error_open(filename);
        uwsgi_unlock(uspool->lock);
        return 0;
    }

    // now lock the file, it will no be runnable, until the lock is not removed
    // a race could come if the spooler take the file before fcntl is called
    // in such case the spooler will detect a zeroed file and will retry later
    if (uwsgi_fcntl_lock(fd)) {
        close(fd);
        uwsgi_unlock(uspool->lock);
        return 0;
    }

    uh.modifier1 = 17;
    uh.modifier2 = 0;
    uh.pktsize = (uint16_t) size;
#ifdef __BIG_ENDIAN__
    uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif

    if (write(fd, &uh, 4) != 4) {
        goto clear;
    }

    if (write(fd, buffer, size) != size) {
        goto clear;
    }

    if (body && body_len > 0) {
        if ((size_t)write(fd, body, body_len) != body_len) {
            goto clear;
        }
    }

    if (at > 0) {
        struct timeval tv[2];
        tv[0].tv_sec = at;
        tv[0].tv_usec = 0;
        tv[1].tv_sec = at;
        tv[1].tv_usec = 0;
#ifdef __sun__
        if (futimesat(fd, NULL, tv)) {
#else
        if (futimes(fd, tv)) {
#endif
            uwsgi_error("futimes()");
        }
    }

    // here the file will be unlocked too
    close(fd);

    if (!uwsgi.spooler_quiet)
        uwsgi_log("[spooler] written %d bytes to file %s\n", size + body_len + 4, filename);

    // and here waiting threads can continue
    uwsgi_unlock(uspool->lock);

    /*	wake up the spoolers attached to the specified dir ... (HACKY)
    	no need to fear races, as USR1 is harmless an all of the uWSGI processes...
    	it could be a problem if a new process takes the old pid, but modern systems should avoid that
    */

    struct uwsgi_spooler *spoolers = uwsgi.spoolers;
    while(spoolers) {
        if (!strcmp(spoolers->dir, uspool->dir)) {
            if (spoolers->pid > 0 && spoolers->running == 0) {
                (void) kill(spoolers->pid, SIGUSR1);
            }
        }
        spoolers = spoolers->next;
    }

    return 1;


clear:
    uwsgi_unlock(uspool->lock);
    uwsgi_error("write()");
    if (unlink(filename)) {
        uwsgi_error("unlink()");
    }
    // unlock the file too
    close(fd);
    return 0;
}



void spooler(struct uwsgi_spooler *uspool) {

    // prevent process blindly reading stdin to make mess
    int nullfd;

    // asked by Marco Beri
#ifdef __HAIKU__
#ifdef UWSGI_DEBUG
    uwsgi_log("lowering spooler priority to %d\n", B_LOW_PRIORITY);
#endif
    set_thread_priority(find_thread(NULL), B_LOW_PRIORITY);
#else
#ifdef UWSGI_DEBUG
    uwsgi_log("lowering spooler priority to %d\n", PRIO_MAX);
#endif
    setpriority(PRIO_PROCESS, getpid(), PRIO_MAX);
#endif

    nullfd = open("/dev/null", O_RDONLY);
    if (nullfd < 0) {
        uwsgi_error_open("/dev/null");
        exit(1);
    }

    if (nullfd != 0) {
        dup2(nullfd, 0);
        close(nullfd);
    }

    int spooler_event_queue = event_queue_init();
    int interesting_fd = -1;

    if (uwsgi.master_process) {
        event_queue_add_fd_read(spooler_event_queue, uwsgi.shared->spooler_signal_pipe[1]);
    }

    // reset the tasks counter
    uspool->tasks = 0;

    for (;;) {


        if (chdir(uspool->dir)) {
            uwsgi_error("chdir()");
            exit(1);
        }

        if (uwsgi.spooler_ordered) {
#ifdef __linux__
            spooler_scandir(uspool, NULL);
#else
            spooler_readdir(uspool, NULL);
#endif
        }
        else {
            spooler_readdir(uspool, NULL);
        }

        int timeout = uwsgi.shared->spooler_frequency;
        if (wakeup > 0) {
            timeout = 0;
        }

        if (event_queue_wait(spooler_event_queue, timeout, &interesting_fd) > 0) {
            if (uwsgi.master_process) {
                if (interesting_fd == uwsgi.shared->spooler_signal_pipe[1]) {
                    uwsgi_receive_signal(interesting_fd, "spooler", (int) getpid());
                }
            }
        }

        // avoid races
        uint64_t tmp_wakeup = wakeup;
        if (tmp_wakeup > 0) {
            tmp_wakeup--;
        }
        wakeup = tmp_wakeup;

        // need to recycle ?
        if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t)uwsgi.spooler_max_tasks) {
            uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
            end_me(0);
        }

    }
}
예제 #19
0
파일: spooler.c 프로젝트: smartstudy/uwsgi
void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {

    int i, ret;

    char spool_buf[0xffff];
    struct uwsgi_header uh;
    char *body = NULL;
    size_t body_len = 0;

    int spool_fd;

    if (!dir) dir = uspool->dir;

    if (!strncmp("uwsgi_spoolfile_on_", task, 19) || (uwsgi.spooler_ordered && is_a_number(task))) {
        struct stat sf_lstat;
        if (lstat(task, &sf_lstat)) {
            return;
        }

        // a spool request for the future
        if (sf_lstat.st_mtime > uwsgi_now()) {
            return;
        }

#ifdef __linux__
        if (S_ISDIR(sf_lstat.st_mode) && uwsgi.spooler_ordered) {
            if (chdir(task)) {
                uwsgi_error("chdir()");
                return;
            }
            char *prio_path = realpath(".", NULL);
            spooler_scandir(uspool, prio_path);
            free(prio_path);
            if (chdir(dir)) {
                uwsgi_error("chdir()");
            }
            return;
        }
#endif
        if (!S_ISREG(sf_lstat.st_mode)) {
            return;
        }
        if (!access(task, R_OK | W_OK)) {

            spool_fd = open(task, O_RDWR);

            if (spool_fd < 0) {
                if (errno != ENOENT)
                    uwsgi_error_open(task);
                return;
            }

            // check if the file is locked by another process
            if (uwsgi_fcntl_is_locked(spool_fd)) {
                uwsgi_protected_close(spool_fd);
                return;
            }

            // unlink() can destroy the lock !!!
            if (access(task, R_OK | W_OK)) {
                uwsgi_protected_close(spool_fd);
                return;
            }

            ssize_t rlen = uwsgi_protected_read(spool_fd, &uh, 4);

            if (rlen != 4) {
                // it could be here for broken file or just opened one
                if (rlen < 0)
                    uwsgi_error("read()");
                uwsgi_protected_close(spool_fd);
                return;
            }

#ifdef __BIG_ENDIAN__
            uh.pktsize = uwsgi_swap16(uh.pktsize);
#endif

            if (uwsgi_protected_read(spool_fd, spool_buf, uh.pktsize) != uh.pktsize) {
                uwsgi_error("read()");
                destroy_spool(dir, task);
                uwsgi_protected_close(spool_fd);
                return;
            }

            // body available ?
            if (sf_lstat.st_size > (uh.pktsize+4)) {
                body_len = sf_lstat.st_size - (uh.pktsize+4);
                body = uwsgi_malloc(body_len);
                if ((size_t)uwsgi_protected_read(spool_fd, body, body_len) != body_len) {
                    uwsgi_error("read()");
                    destroy_spool(dir, task);
                    uwsgi_protected_close(spool_fd);
                    free(body);
                    return;
                }
            }

            // now the task is running and should not be waken up
            uspool->running = 1;

            if (!uwsgi.spooler_quiet)
                uwsgi_log("[spooler %s pid: %d] managing request %s ...\n", uspool->dir, (int) uwsgi.mypid, task);


            // chdir before running the task (if requested)
            if (uwsgi.spooler_chdir) {
                if (chdir(uwsgi.spooler_chdir)) {
                    uwsgi_error("chdir()");
                }
            }

            int callable_found = 0;
            for(i=0; i<256; i++) {
                if (uwsgi.p[i]->spooler) {
                    time_t now = uwsgi_now();
                    if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
                        set_spooler_harakiri(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI]);
                    }
                    ret = uwsgi.p[i]->spooler(task, spool_buf, uh.pktsize, body, body_len);
                    if(uwsgi.shared->options[UWSGI_OPTION_SPOOLER_HARAKIRI] > 0) {
                        set_spooler_harakiri(0);
                    }
                    if (ret == 0) continue;
                    callable_found = 1;
                    // increase task counter
                    uspool->tasks++;
                    if (ret == -2) {
                        if (!uwsgi.spooler_quiet)
                            uwsgi_log("[spooler %s pid: %d] done with task %s after %d seconds\n", uspool->dir, (int) uwsgi.mypid, task, uwsgi_now()-now);
                        destroy_spool(dir, task);
                    }
                    // re-spool it
                    break;
                }
            }

            if (body)
                free(body);

            // here we free and unlock the task
            uwsgi_protected_close(spool_fd);
            uspool->running = 0;

            if (chdir(dir)) {
                uwsgi_error("chdir()");
                uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
                exit(1);
            }

            if (!callable_found) {
                uwsgi_log("unable to find the spooler function, have you loaded it into the spooler process ?\n");
            }

        }
    }
}
예제 #20
0
파일: spooler.c 프로젝트: Perkville/uwsgi
void spooler_manage_task(struct uwsgi_spooler *uspool, char *dir, char *task) {

	int i, ret;

	char spool_buf[0xffff];
	struct uwsgi_header uh;
	char *body = NULL;
	size_t body_len = 0;

	int spool_fd;

	if (!dir)
		dir = uspool->dir;

	if (!strncmp("uwsgi_spoolfile_on_", task, 19) || (uwsgi.spooler_ordered && is_a_number(task))) {
		struct stat sf_lstat;

		if (lstat(task, &sf_lstat)) {
			return;
		}

		// a spool request for the future
		if (sf_lstat.st_mtime > uwsgi_now()) {
			return;
		}

		if (S_ISDIR(sf_lstat.st_mode) && uwsgi.spooler_ordered) {
			if (chdir(task)) {
				uwsgi_error("spooler_manage_task()/chdir()");
				return;
			}
#ifdef __UCLIBC__ 
			char *prio_path = uwsgi_malloc(PATH_MAX);
			realpath(".", prio_path);		
#else 
			char *prio_path = realpath(".", NULL);
#endif
			spooler_scandir(uspool, prio_path);
			free(prio_path);
			if (chdir(dir)) {
				uwsgi_error("spooler_manage_task()/chdir()");
			}
			return;
		}
		if (!S_ISREG(sf_lstat.st_mode)) {
			return;
		}
		if (!access(task, R_OK | W_OK)) {

			spool_fd = open(task, O_RDWR);

			if (spool_fd < 0) {
				if (errno != ENOENT)
					uwsgi_error_open(task);
				return;
			}

			if (uwsgi_spooler_read_header(task, spool_fd, &uh))
				return;

			// access lstat second time after getting a lock
			// first-time lstat could be dirty (for example between writes in master)
			if (lstat(task, &sf_lstat)) {
				return;
			}

			if (uwsgi_spooler_read_content(spool_fd, spool_buf, &body, &body_len, &uh, &sf_lstat)) {
				destroy_spool(dir, task);
				return;
			}

			// now the task is running and should not be woken up
			uspool->running = 1;
			// this is used in cheap mode for making decision about who must die
			uspool->last_task_managed = uwsgi_now();

			if (!uwsgi.spooler_quiet)
				uwsgi_log("[spooler %s pid: %d] managing request %s ...\n", uspool->dir, (int) uwsgi.mypid, task);


			// chdir before running the task (if requested)
			if (uwsgi.spooler_chdir) {
				if (chdir(uwsgi.spooler_chdir)) {
					uwsgi_error("spooler_manage_task()/chdir()");
				}
			}

			int callable_found = 0;
			for (i = 0; i < 256; i++) {
				if (uwsgi.p[i]->spooler) {
					time_t now = uwsgi_now();
					if (uwsgi.harakiri_options.spoolers > 0) {
						set_spooler_harakiri(uwsgi.harakiri_options.spoolers);
					}
					ret = uwsgi.p[i]->spooler(task, spool_buf, uh._pktsize, body, body_len);
					if (uwsgi.harakiri_options.spoolers > 0) {
						set_spooler_harakiri(0);
					}
					if (ret == 0)
						continue;
					callable_found = 1;
					// increase task counter
					uspool->tasks++;
					if (ret == -2) {
						if (!uwsgi.spooler_quiet)
							uwsgi_log("[spooler %s pid: %d] done with task %s after %lld seconds\n", uspool->dir, (int) uwsgi.mypid, task, (long long) uwsgi_now() - now);
						destroy_spool(dir, task);
					}
					// re-spool it
					break;
				}
			}

			if (body)
				free(body);

			// here we free and unlock the task
			uwsgi_protected_close(spool_fd);
			uspool->running = 0;


			// need to recycle ?
			if (uwsgi.spooler_max_tasks > 0 && uspool->tasks >= (uint64_t) uwsgi.spooler_max_tasks) {
				uwsgi_log("[spooler %s pid: %d] maximum number of tasks reached (%d) recycling ...\n", uspool->dir, (int) uwsgi.mypid, uwsgi.spooler_max_tasks);
				end_me(0);
			}


			if (chdir(dir)) {
				uwsgi_error("chdir()");
				uwsgi_log("[spooler] something horrible happened to the spooler. Better to kill it.\n");
				exit(1);
			}

			if (!callable_found) {
				uwsgi_log("unable to find the spooler function, have you loaded it into the spooler process ?\n");
			}

		}
	}
}
예제 #21
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; 
}
예제 #22
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;
}
예제 #23
0
char *uwsgi_rsa_sign(char *algo_key, char *message, size_t message_len, unsigned int *s_len) {

        // openssl could not be initialized
        if (!uwsgi.ssl_initialized) {
                uwsgi_ssl_init();
        }

        *s_len = 0;
        EVP_PKEY *pk = NULL;

        char *algo = uwsgi_str(algo_key);
        char *colon = strchr(algo, ':');
        if (!colon) {
                uwsgi_log("invalid RSA signature syntax, must be: <digest>:<pemfile>\n");
                free(algo);
                return NULL;
        }

        *colon = 0;
        char *keyfile = colon + 1;
        char *signature = NULL;

        FILE *kf = fopen(keyfile, "r");
        if (!kf) {
                uwsgi_error_open(keyfile);
                free(algo);
                return NULL;
        }

        if (PEM_read_PrivateKey(kf, &pk, NULL, NULL) == 0) {
                uwsgi_log("unable to load private key: %s\n", keyfile);
                free(algo);
                fclose(kf);
                return NULL;
        }

        fclose(kf);

        EVP_MD_CTX *ctx = EVP_MD_CTX_create();
        if (!ctx) {
                free(algo);
                EVP_PKEY_free(pk);
                return NULL;
        }

        const EVP_MD *md = EVP_get_digestbyname(algo);
        if (!md) {
                uwsgi_log("unknown digest algo: %s\n", algo);
                free(algo);
                EVP_PKEY_free(pk);
                EVP_MD_CTX_destroy(ctx);
                return NULL;
        }

        *s_len = EVP_PKEY_size(pk);
        signature = uwsgi_malloc(*s_len);

	if (EVP_SignInit_ex(ctx, md, NULL) == 0) {
                ERR_print_errors_fp(stderr);
                free(signature);
                signature = NULL;
                *s_len = 0;
                goto clear;
        }

        if (EVP_SignUpdate(ctx, message, message_len) == 0) {
                ERR_print_errors_fp(stderr);
                free(signature);
                signature = NULL;
                *s_len = 0;
                goto clear;
        }


        if (EVP_SignFinal(ctx, (unsigned char *) signature, s_len, pk) == 0) {
                ERR_print_errors_fp(stderr);
                free(signature);
                signature = NULL;
                *s_len = 0;
                goto clear;
        }

clear:
        free(algo);
        EVP_PKEY_free(pk);
        EVP_MD_CTX_destroy(ctx);
        return signature;

}
예제 #24
0
void uwsgi_build_plugin(char *directory) {

	if (!uwsgi_file_exists(UWSGI_BUILD_DIR)) {
		if (mkdir(UWSGI_BUILD_DIR, S_IRWXU) < 0) {
        		uwsgi_error("uwsgi_build_plugin()/mkdir() " UWSGI_BUILD_DIR "/");
			_exit(1);
		}
	}

	char *dot_h = uwsgi_get_dot_h();
	if (!dot_h) {
		uwsgi_log("unable to generate uwsgi.h");
		_exit(1);
	}

	if (strlen(dot_h) == 0) {
		free(dot_h);
		uwsgi_log("invalid uwsgi.h");
		_exit(1);
	}

	int dot_h_fd = open(UWSGI_BUILD_DIR "/uwsgi.h", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
	if (dot_h_fd < 0) {
		uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgi.h");
		free(dot_h);
		_exit(1);
	}

	ssize_t dot_h_len = (ssize_t) strlen(dot_h);
	if (write(dot_h_fd, dot_h, dot_h_len) != dot_h_len) {
		uwsgi_error("uwsgi_build_plugin()/write()");
		_exit(1);
	}

	char *config_py = uwsgi_get_config_py();
        if (!config_py) {
                uwsgi_log("unable to generate uwsgiconfig.py");
                _exit(1);
        }

        if (strlen(config_py) == 0) {
                uwsgi_log("invalid uwsgiconfig.py");
                _exit(1);
        }

        int config_py_fd = open(UWSGI_BUILD_DIR "/uwsgiconfig.py", O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
        if (config_py_fd < 0) {
                uwsgi_error_open(UWSGI_BUILD_DIR "/uwsgiconfig.py");
                _exit(1);
        }

        ssize_t config_py_len = (ssize_t) strlen(config_py);
        if (write(config_py_fd, config_py, config_py_len) != config_py_len) {
                uwsgi_error("uwsgi_build_plugin()/write()");
                _exit(1);
        }

	char *cflags = uwsgi_get_cflags();
	if (!cflags) {
		uwsgi_log("unable to find cflags\n");
		_exit(1);
	}
	if (strlen(cflags) == 0) {
		uwsgi_log("invalid cflags\n");
		_exit(1);
	}

	if (setenv("UWSGI_PLUGINS_BUILDER_CFLAGS", cflags, 1)) {
		uwsgi_error("uwsgi_build_plugin()/setenv()");
		_exit(1);
	}
	
	// now run the python script
	char *argv[6];

	argv[0] = getenv("PYTHON");
	if (!argv[0]) argv[0] = "python";

	argv[1] = UWSGI_BUILD_DIR "/uwsgiconfig.py";
	argv[2] = "--extra-plugin";
	char *space = strchr(directory, ' ');
	if (space) {
		*space = 0;
		argv[3] = directory;
                argv[4] = space+1;
		argv[5] = NULL;
	}
	else {
		argv[3] = directory;
		argv[4] = NULL;
	}

	execvp(argv[0], argv);
	// never here...	
	_exit(1);
}
예제 #25
0
파일: queue.c 프로젝트: arteme/uwsgi
void uwsgi_init_queue() {
	if (!uwsgi.queue_blocksize)
		uwsgi.queue_blocksize = 8192;

	if ((uwsgi.queue_blocksize * uwsgi.queue_size) % uwsgi.page_size != 0) {
		uwsgi_log("invalid queue size/blocksize %llu: must be a multiple of memory page size (%d bytes)\n", (unsigned long long) uwsgi.queue_blocksize, uwsgi.page_size);
		exit(1);
	}



	if (uwsgi.queue_store) {
		uwsgi.queue_filesize = uwsgi.queue_blocksize * uwsgi.queue_size + 16;
		int queue_fd;
		struct stat qst;

		if (stat(uwsgi.queue_store, &qst)) {
			uwsgi_log("creating a new queue store file: %s\n", uwsgi.queue_store);
			queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
			if (queue_fd >= 0) {
				// fill the queue store
				if (ftruncate(queue_fd, uwsgi.queue_filesize)) {
					uwsgi_log("ftruncate()");
					exit(1);
				}
			}
		}
		else {
			if ((size_t) qst.st_size != uwsgi.queue_filesize || !S_ISREG(qst.st_mode)) {
				uwsgi_log("invalid queue store file. Please remove it or fix queue blocksize/items to match its size\n");
				exit(1);
			}
			queue_fd = open(uwsgi.queue_store, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
			uwsgi_log("recovered queue from backing store file: %s\n", uwsgi.queue_store);
		}

		if (queue_fd < 0) {
			uwsgi_error_open(uwsgi.queue_store);
			exit(1);
		}
		uwsgi.queue = mmap(NULL, uwsgi.queue_filesize, PROT_READ | PROT_WRITE, MAP_SHARED, queue_fd, 0);

		// fix header
		uwsgi.queue_header = uwsgi.queue;
		uwsgi.queue += 16;
	}
	else {
		uwsgi.queue = mmap(NULL, (uwsgi.queue_blocksize * uwsgi.queue_size) + 16, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
		// fix header
		uwsgi.queue_header = uwsgi.queue;
		uwsgi.queue += 16;
		uwsgi.queue_header->pos = 0;
		uwsgi.queue_header->pull_pos = 0;
	}
	if (!uwsgi.queue) {
		uwsgi_error("mmap()");
		exit(1);
	}



	uwsgi.queue_lock = uwsgi_rwlock_init("queue");

	uwsgi_log("*** Queue subsystem initialized: %dMB preallocated ***\n", (uwsgi.queue_blocksize * uwsgi.queue_size) / (1024 * 1024));
}
예제 #26
0
파일: mongrel2.c 프로젝트: avar/uwsgi
// dumb/fake tnetstring implementation...all is a string
static int uwsgi_mongrel2_tnetstring_parse(struct wsgi_request *wsgi_req, char *buf, int len) {

	char *ptr = buf;
	char *watermark = buf + len;
	char *key = NULL;
	size_t keylen = 0;
	char *val = NULL;
	size_t vallen = 0;
	uint16_t script_name_len = 0;
	char *query_string = NULL;
	uint16_t query_string_len = 0;
	int async_upload = 0;

	// set an empty SCRIPT_NAME
	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SCRIPT_NAME", 11, "", 0);

	while (ptr < watermark) {

		ptr = uwsgi_netstring(ptr, len - (ptr - buf), &key, &keylen);
		if (ptr == NULL)
			break;
		// empty keys are not allowed
		if (keylen == 0)
			break;

		if (ptr >= watermark)
			break;

		ptr = uwsgi_netstring(ptr, len - (ptr - buf), &val, &vallen);
		if (ptr == NULL)
			break;


		if (key[0] < 97) {
			if (!uwsgi_strncmp("METHOD", 6, key, keylen)) {
				if (!uwsgi_strncmp("JSON", 4, val, vallen)) {
					return -1;
				}
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_METHOD", 14, val, vallen);
			}
			else if (!uwsgi_strncmp("VERSION", 7, key, keylen)) {
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PROTOCOL", 15, val, vallen);
			}
			else if (!uwsgi_strncmp("QUERY", 5, key, keylen)) {
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, val, vallen);
				query_string = val;
				query_string_len = vallen;
			}
			else if (!uwsgi_strncmp("PATH", 4, key, keylen)) {
				wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "PATH_INFO", 9, val + script_name_len, vallen - script_name_len);
				if (query_string_len) {
					char *request_uri = uwsgi_concat3n(val, vallen, "?", 1, query_string, query_string_len);
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, request_uri, vallen + 1 + query_string_len);
					free(request_uri);
				}
				else {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REQUEST_URI", 11, val, vallen);
				}
			}
		}
		else {
			// add header
			if (!uwsgi_strncmp("host", 4, key, keylen)) {
				char *colon = memchr(val, ':', vallen);
				if (colon) {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, colon + 1, vallen - ((colon + 1) - val));
				}
				else {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_PORT", 11, "80", 2);
				}
			}
			else if (!uwsgi_strncmp("content-length", 14, key, keylen)) {
				wsgi_req->post_cl = uwsgi_str_num(val, vallen);
			}
			else if (!uwsgi_strncmp("x-mongrel2-upload-done", 22, key, keylen)) {
				char *post_filename = uwsgi_concat2n(val, vallen, "", 0);
				wsgi_req->post_file = fopen(post_filename, "r");
				if (!wsgi_req->post_file) {
					uwsgi_error_open(post_filename);
					wsgi_req->do_not_log = 1;
				}
				async_upload += 2;
				free(post_filename);
			}
			else if (!uwsgi_strncmp("x-forwarded-for", 15, key, keylen)) {
				char *colon = memchr(val, ',', vallen);
				if (colon) {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, colon + 1, (colon + 1) - val);
				}
				else {
					wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "REMOTE_ADDR", 11, val, vallen);
				}
			}
			else if (!uwsgi_strncmp("x-mongrel2-upload-start", 23, key, keylen)) {
				async_upload += 1;
			}
			wsgi_req->uh->pktsize += proto_base_add_uwsgi_header(wsgi_req, key, keylen, val, vallen);
		}
	}

	wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "SERVER_NAME", 11, uwsgi.hostname, uwsgi.hostname_len);

	if (query_string == NULL) {
		// always set QUERY_STRING
		wsgi_req->uh->pktsize += proto_base_add_uwsgi_var(wsgi_req, "QUERY_STRING", 12, "", 0);
	}

	// reject uncomplete upload
	if (async_upload == 1) {
		return -1;
	}
	return 0;
}
예제 #27
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;

}
예제 #28
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);
	}
}
예제 #29
0
PyObject *uwsgi_pyimport_by_filename(char *name, char *filename) {

#ifdef UWSGI_PYPY
	uwsgi_log("import by filename is currently not supported on PyPy !!!\n");
	return NULL;
#else
	FILE *pyfile;
	struct _node *py_file_node = NULL;
	PyObject *py_compiled_node, *py_file_module;
	int is_a_package = 0;
	struct stat pystat;
	char *real_filename = filename;


	if (!uwsgi_check_scheme(filename)) {

		pyfile = fopen(filename, "r");
		if (!pyfile) {
			uwsgi_log("failed to open python file %s\n", filename);
			return NULL;
		}

		if (fstat(fileno(pyfile), &pystat)) {
			uwsgi_error("fstat()");
			return NULL;
		}

		if (S_ISDIR(pystat.st_mode)) {
			is_a_package = 1;
			fclose(pyfile);
			real_filename = uwsgi_concat2(filename, "/__init__.py");
			pyfile = fopen(real_filename, "r");
			if (!pyfile) {
				uwsgi_error_open(real_filename);
				free(real_filename);
				return NULL;
			}
		}

		py_file_node = PyParser_SimpleParseFile(pyfile, real_filename, Py_file_input);
		if (!py_file_node) {
			PyErr_Print();
			uwsgi_log("failed to parse file %s\n", real_filename);
			if (is_a_package)
				free(real_filename);
			fclose(pyfile);
			return NULL;
		}

		fclose(pyfile);
	}
	else {
		int pycontent_size = 0;
		char *pycontent = uwsgi_open_and_read(filename, &pycontent_size, 1, NULL);

		if (pycontent) {
			py_file_node = PyParser_SimpleParseString(pycontent, Py_file_input);
			if (!py_file_node) {
				PyErr_Print();
				uwsgi_log("failed to parse url %s\n", real_filename);
				return NULL;
			}
		}
	}

	py_compiled_node = (PyObject *) PyNode_Compile(py_file_node, real_filename);

	if (!py_compiled_node) {
		PyErr_Print();
		uwsgi_log("failed to compile python file %s\n", real_filename);
		return NULL;
	}

	if (is_a_package) {
		py_file_module = PyImport_AddModule(name);
		if (py_file_module) {
			PyModule_AddObject(py_file_module, "__path__", Py_BuildValue("[O]", PyString_FromString(filename)));
		}
		free(real_filename);
	}

	py_file_module = PyImport_ExecCodeModule(name, py_compiled_node);
	if (!py_file_module) {
		PyErr_Print();
		return NULL;
	}

	Py_DECREF(py_compiled_node);

	return py_file_module;
#endif

}
예제 #30
0
// create the logpipe
void create_logpipe(void) {

#if defined(SOCK_SEQPACKET) && defined(__linux__)
        if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, uwsgi.shared->worker_log_pipe)) {
#else
        if (socketpair(AF_UNIX, SOCK_DGRAM, 0, uwsgi.shared->worker_log_pipe)) {
#endif
                uwsgi_error("socketpair()\n");
                exit(1);
        }

        uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[0]);
        uwsgi_socket_nb(uwsgi.shared->worker_log_pipe[1]);

        if (uwsgi.shared->worker_log_pipe[1] != 1) {
                if (dup2(uwsgi.shared->worker_log_pipe[1], 1) < 0) {
                        uwsgi_error("dup2()");
                        exit(1);
                }
        }

        if (dup2(1, 2) < 0) {
                uwsgi_error("dup2()");
                exit(1);
        }

}

#ifdef UWSGI_ZEROMQ
// the zeromq logger
ssize_t uwsgi_zeromq_logger(struct uwsgi_logger *ul, char *message, size_t len) {

        if (!ul->configured) {

                if (!ul->arg) {
                        uwsgi_log_safe("invalid zeromq syntax\n");
                        exit(1);
                }

                void *ctx = uwsgi_zeromq_init();

                ul->data = zmq_socket(ctx, ZMQ_PUSH);
                if (ul->data == NULL) {
                        uwsgi_error_safe("zmq_socket()");
                        exit(1);
                }

                if (zmq_connect(ul->data, ul->arg) < 0) {
                        uwsgi_error_safe("zmq_connect()");
                        exit(1);
                }

                ul->configured = 1;
        }

        zmq_msg_t msg;
        if (zmq_msg_init_size(&msg, len) == 0) {
                memcpy(zmq_msg_data(&msg), message, len);
#if ZMQ_VERSION >= ZMQ_MAKE_VERSION(3,0,0)
                zmq_sendmsg(ul->data, &msg, 0);
#else
                zmq_send(ul->data, &msg, 0);
#endif
                zmq_msg_close(&msg);
        }

        return 0;
}
#endif


// log to the specified file or udp address
void logto(char *logfile) {

        int fd;

#ifdef UWSGI_UDP
        char *udp_port;
        struct sockaddr_in udp_addr;

        udp_port = strchr(logfile, ':');
        if (udp_port) {
                udp_port[0] = 0;
                if (!udp_port[1] || !logfile[0]) {
                        uwsgi_log("invalid udp address\n");
                        exit(1);
                }

                fd = socket(AF_INET, SOCK_DGRAM, 0);
                if (fd < 0) {
                        uwsgi_error("socket()");
                        exit(1);
                }

                memset(&udp_addr, 0, sizeof(struct sockaddr_in));

                udp_addr.sin_family = AF_INET;
                udp_addr.sin_port = htons(atoi(udp_port + 1));
                char *resolved = uwsgi_resolve_ip(logfile);
                if (resolved) {
                        udp_addr.sin_addr.s_addr = inet_addr(resolved);
                }
                else {
                        udp_addr.sin_addr.s_addr = inet_addr(logfile);
                }

                if (connect(fd, (const struct sockaddr *) &udp_addr, sizeof(struct sockaddr_in)) < 0) {
                        uwsgi_error("connect()");
                        exit(1);
                }
        }
        else {
#endif
                if (uwsgi.log_truncate) {
                        fd = open(logfile, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP);
                }
                else {
                        fd = open(logfile, O_RDWR | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP);
                }
                if (fd < 0) {
                        uwsgi_error_open(logfile);
                        exit(1);
                }
                uwsgi.logfile = logfile;

                if (uwsgi.chmod_logfile_value) {
                        if (chmod(uwsgi.logfile, uwsgi.chmod_logfile_value)) {
                                uwsgi_error("chmod()");
                        }
                }
#ifdef UWSGI_UDP
        }
#endif


        /* stdout */
        if (fd != 1) {
                if (dup2(fd, 1) < 0) {
                        uwsgi_error("dup2()");
                        exit(1);
                }
                close(fd);
        }

        /* stderr */
        if (dup2(1, 2) < 0) {
                uwsgi_error("dup2()");
                exit(1);
        }
}