mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-07 06:06:08 +00:00
Zerg mode added
This commit is contained in:
@@ -226,6 +226,12 @@ void master_loop(char **argv, char **environ) {
|
||||
if (uwsgi.has_emperor) {
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.emperor_fd);
|
||||
}
|
||||
|
||||
if (uwsgi.zerg_server) {
|
||||
uwsgi.zerg_server_fd = bind_to_unix(uwsgi.zerg_server, uwsgi.listen_queue, 0, 0);
|
||||
event_queue_add_fd_read(uwsgi.master_queue, uwsgi.zerg_server_fd);
|
||||
uwsgi_log("*** Zerg server enabled on %s ***\n", uwsgi.zerg_server);
|
||||
}
|
||||
#ifdef UWSGI_UDP
|
||||
if (uwsgi.udp_socket) {
|
||||
udp_fd = bind_to_udp(uwsgi.udp_socket, 0, 0);
|
||||
@@ -632,6 +638,56 @@ void master_loop(char **argv, char **environ) {
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.zerg_server) {
|
||||
if (interesting_fd == uwsgi.zerg_server_fd) {
|
||||
struct sockaddr_un zsun;
|
||||
socklen_t zsun_len = sizeof(struct sockaddr_un);
|
||||
int zerg_client = accept(uwsgi.zerg_server_fd, (struct sockaddr *) &zsun, &zsun_len);
|
||||
if (zerg_client < 0) {
|
||||
uwsgi_error("zerg: accept()");
|
||||
continue;
|
||||
}
|
||||
|
||||
struct msghdr zerg_msg;
|
||||
void *zerg_msg_control = uwsgi_malloc(CMSG_SPACE (sizeof (int) * uwsgi_count_sockets(uwsgi.sockets)));
|
||||
struct iovec zerg_iov;
|
||||
struct cmsghdr *cmsg;
|
||||
|
||||
zerg_iov.iov_base = "uwsgi-zerg";
|
||||
zerg_iov.iov_len = 10;
|
||||
|
||||
zerg_msg.msg_name = NULL;
|
||||
zerg_msg.msg_namelen = 0;
|
||||
zerg_msg.msg_iov = &zerg_iov;
|
||||
zerg_msg.msg_iovlen = 1;
|
||||
zerg_msg.msg_flags = 0;
|
||||
zerg_msg.msg_control = zerg_msg_control;
|
||||
zerg_msg.msg_controllen = CMSG_SPACE (sizeof (int) * uwsgi_count_sockets(uwsgi.sockets));
|
||||
|
||||
cmsg = CMSG_FIRSTHDR (&zerg_msg);
|
||||
cmsg->cmsg_len = CMSG_LEN (sizeof (int) * uwsgi_count_sockets(uwsgi.sockets));
|
||||
cmsg->cmsg_level = SOL_SOCKET;
|
||||
cmsg->cmsg_type = SCM_RIGHTS;
|
||||
|
||||
struct uwsgi_socket *uwsgi_sock = uwsgi.sockets;
|
||||
unsigned char *zerg_fd_ptr = CMSG_DATA(cmsg);
|
||||
while(uwsgi_sock) {
|
||||
memcpy(zerg_fd_ptr, &uwsgi_sock->fd, sizeof(int));
|
||||
zerg_fd_ptr += sizeof(int);
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
if (sendmsg(zerg_client, &zerg_msg, 0) < 0) {
|
||||
uwsgi_error("sendmsg()");
|
||||
}
|
||||
|
||||
|
||||
close(zerg_client);
|
||||
|
||||
free(zerg_msg_control);
|
||||
}
|
||||
}
|
||||
|
||||
if (uwsgi.has_emperor) {
|
||||
if (interesting_fd == uwsgi.emperor_fd) {
|
||||
char byte;
|
||||
|
||||
@@ -495,6 +495,17 @@ int bind_to_tcp(char *socket_name, int listen_queue, char *tcp_port) {
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
|
||||
if (uwsgi.reuse_port) {
|
||||
#ifdef SO_REUSEPORT
|
||||
if (setsockopt(serverfd, SOL_SOCKET, SO_REUSEPORT, (const void *) &reuse_port, sizeof(int)) < 0) {
|
||||
uwsgi_error("setsockopt()");
|
||||
uwsgi_nuclear_blast();
|
||||
}
|
||||
#else
|
||||
uwsgi_log("!!! your system does not support SO_REUSEPORT !!!\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!uwsgi.no_defer_accept) {
|
||||
|
||||
#ifdef __linux__
|
||||
@@ -628,6 +639,17 @@ int timed_connect(struct pollfd *fdpoll, const struct sockaddr *addr, int addr_s
|
||||
|
||||
}
|
||||
|
||||
int uwsgi_count_sockets(struct uwsgi_socket *uwsgi_sock) {
|
||||
|
||||
int count = 0;
|
||||
while(uwsgi_sock) {
|
||||
count++;
|
||||
uwsgi_sock = uwsgi_sock->next;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int uwsgi_get_socket_num(struct uwsgi_socket *uwsgi_sock) {
|
||||
|
||||
int count = 0;
|
||||
@@ -726,6 +748,15 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
|
||||
}
|
||||
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, "");
|
||||
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);
|
||||
return;
|
||||
}
|
||||
if (!strcmp(usa.sa_un.sun_path+abstract, uwsgi_sock->name+abstract)) {
|
||||
uwsgi_sock->fd = fd;
|
||||
uwsgi_sock->family = AF_UNIX;
|
||||
@@ -751,6 +782,17 @@ void uwsgi_add_socket_from_fd(struct uwsgi_socket *uwsgi_sock, int fd) {
|
||||
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, "");
|
||||
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);
|
||||
free(computed_addr);
|
||||
return;
|
||||
}
|
||||
char *asterisk = strchr(uwsgi_sock->name, '*');
|
||||
int match = 1;
|
||||
if (asterisk) {
|
||||
|
||||
@@ -2336,3 +2336,73 @@ int uwsgi_run_command(char *command) {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
int *uwsgi_attach_fd(int fd, int count, char *code, size_t code_len) {
|
||||
|
||||
struct msghdr msg;
|
||||
ssize_t len;
|
||||
char *id = NULL;
|
||||
|
||||
struct iovec iov;
|
||||
struct cmsghdr *cmsg;
|
||||
int *ret;
|
||||
int i;
|
||||
|
||||
void *msg_control = uwsgi_malloc(CMSG_SPACE(sizeof(int) * count));
|
||||
|
||||
memset( msg_control, 0, CMSG_SPACE(sizeof(int) * count));
|
||||
|
||||
if (code && code_len > 0) {
|
||||
id = uwsgi_malloc(code_len);
|
||||
memset(id, 0, code_len);
|
||||
}
|
||||
|
||||
iov.iov_base = id;
|
||||
iov.iov_len = code_len;
|
||||
memset(&msg, 0, sizeof(msg));
|
||||
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_control = msg_control;
|
||||
msg.msg_controllen = CMSG_SPACE(sizeof(int) * count);
|
||||
msg.msg_flags = 0;
|
||||
|
||||
len = recvmsg(fd, &msg, 0);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("recvmsg()");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (code && code_len > 0) {
|
||||
if (strcmp(id, code)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
if (!cmsg) return NULL;
|
||||
|
||||
if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = uwsgi_malloc(sizeof(int) * (count + 1));
|
||||
for(i=0;i<count+1;i++) {
|
||||
ret[i] = -1;
|
||||
}
|
||||
|
||||
if ((cmsg->cmsg_len - ((char *)CMSG_DATA(cmsg)- (char *)cmsg)) > (sizeof(int) * (count + 1))) {
|
||||
uwsgi_log("not enough space for sockets data, consider increasing it\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(ret, CMSG_DATA(cmsg), cmsg->cmsg_len - ((char *)CMSG_DATA(cmsg)- (char *)cmsg));
|
||||
|
||||
free(msg_control);
|
||||
if (code && code_len > 0) {
|
||||
free(id);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -208,6 +208,9 @@ static struct option long_base_options[] = {
|
||||
{"namespace-net", required_argument, 0, LONG_ARGS_LINUX_NS_NET},
|
||||
{"ns-net", required_argument, 0, LONG_ARGS_LINUX_NS_NET},
|
||||
#endif
|
||||
{"reuse-port", no_argument, &uwsgi.reuse_port, 1},
|
||||
{"zerg", required_argument, 0, LONG_ARGS_ZERG},
|
||||
{"zerg-server", required_argument, 0, LONG_ARGS_ZERG_SERVER},
|
||||
{"cron", required_argument, 0, LONG_ARGS_CRON},
|
||||
{"loop", required_argument, 0, LONG_ARGS_LOOP},
|
||||
{"worker-exec", required_argument, 0, LONG_ARGS_WORKER_EXEC},
|
||||
@@ -1603,11 +1606,26 @@ int uwsgi_start(void *v_argv) {
|
||||
if (!uwsgi.no_server) {
|
||||
|
||||
//check for inherited sockets
|
||||
if (uwsgi.is_a_reload) {
|
||||
if (uwsgi.is_a_reload || uwsgi.zerg) {
|
||||
|
||||
if (uwsgi.zerg) {
|
||||
int zerg_fd;
|
||||
i = 0;
|
||||
for(;;) {
|
||||
zerg_fd = uwsgi.zerg[i];
|
||||
if (zerg_fd == -1) {
|
||||
break;
|
||||
}
|
||||
uwsgi_sock = uwsgi_new_socket(NULL);
|
||||
uwsgi_add_socket_from_fd(uwsgi_sock, zerg_fd);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
uwsgi_sock = uwsgi.sockets;
|
||||
while (uwsgi_sock) {
|
||||
//a bit overengineering
|
||||
if (uwsgi_sock->name[0] != 0) {
|
||||
if (uwsgi_sock->name[0] != 0 && !uwsgi_sock->bound) {
|
||||
for (j = 3; j < sysconf(_SC_OPEN_MAX); j++) {
|
||||
uwsgi_add_socket_from_fd(uwsgi_sock, j);
|
||||
}
|
||||
@@ -2421,6 +2439,7 @@ static int manage_base_opt(int i, char *optarg) {
|
||||
struct uwsgi_static_map *usm, *old_usm;
|
||||
struct uwsgi_config_template *uct, *old_uct;
|
||||
struct uwsgi_cron *uc, *old_uc;
|
||||
int zerg_fd;
|
||||
|
||||
switch (i) {
|
||||
|
||||
@@ -2949,6 +2968,23 @@ static int manage_base_opt(int i, char *optarg) {
|
||||
case 's':
|
||||
uwsgi_new_socket(generate_socket_name(optarg));
|
||||
return 1;
|
||||
case LONG_ARGS_ZERG:
|
||||
zerg_fd = uwsgi_connect(optarg, 30, 0);
|
||||
if (zerg_fd < 0) {
|
||||
uwsgi_log("--- unable to connect to zerg server ---\n");
|
||||
exit(1);
|
||||
}
|
||||
uwsgi.zerg = uwsgi_attach_fd(zerg_fd, 8, "uwsgi-zerg", 11);
|
||||
if (uwsgi.zerg == NULL) {
|
||||
uwsgi_log("--- invalid data received from zerg-server ---\n");
|
||||
exit(1);
|
||||
}
|
||||
close(zerg_fd);
|
||||
return 1;
|
||||
case LONG_ARGS_ZERG_SERVER:
|
||||
uwsgi.zerg_server = optarg;
|
||||
uwsgi.master_process = 1;
|
||||
return 1;
|
||||
case LONG_ARGS_SHARED_SOCKET:
|
||||
uwsgi_new_shared_socket(generate_socket_name(optarg));
|
||||
return 1;
|
||||
|
||||
@@ -445,6 +445,8 @@ struct uwsgi_opt {
|
||||
#define LONG_ARGS_VASSALS_START_HOOK 17121
|
||||
#define LONG_ARGS_VASSALS_STOP_HOOK 17122
|
||||
#define LONG_ARGS_CRON 17123
|
||||
#define LONG_ARGS_ZERG 17124
|
||||
#define LONG_ARGS_ZERG_SERVER 17125
|
||||
|
||||
|
||||
#define UWSGI_OK 0
|
||||
@@ -863,6 +865,8 @@ struct uwsgi_server {
|
||||
time_t current_time;
|
||||
uint64_t master_cycles;
|
||||
|
||||
int reuse_port;
|
||||
|
||||
int lazy;
|
||||
int cheap;
|
||||
int idle;
|
||||
@@ -903,6 +907,10 @@ struct uwsgi_server {
|
||||
|
||||
char *remap_modifier;
|
||||
|
||||
int *zerg;
|
||||
char *zerg_server;
|
||||
int zerg_server_fd;
|
||||
|
||||
char *chroot;
|
||||
gid_t gid;
|
||||
uid_t uid;
|
||||
@@ -2018,3 +2026,7 @@ void uwsgi_manage_signal_cron(time_t);
|
||||
int uwsgi_run_command(char *);
|
||||
|
||||
void uwsgi_manage_command_cron(time_t);
|
||||
|
||||
int *uwsgi_attach_fd(int, int, char *, size_t);
|
||||
|
||||
int uwsgi_count_sockets(struct uwsgi_socket *);
|
||||
|
||||
Reference in New Issue
Block a user