mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-09-01 02:35:03 +00:00
added adopted-vassals concept
This commit is contained in:
+26
-12
@@ -775,10 +775,12 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
}
|
||||
|
||||
// this will destroy the whole uWSGI instance (and workers)
|
||||
close(c_ui->pipe[0]);
|
||||
if (c_ui->pipe[0] != -1) close(c_ui->pipe[0]);
|
||||
if (c_ui->pipe[1] != -1) close(c_ui->pipe[1]);
|
||||
|
||||
if (c_ui->use_config) {
|
||||
close(c_ui->pipe_config[0]);
|
||||
if (c_ui->pipe_config[0] != -1) close(c_ui->pipe_config[0]);
|
||||
if (c_ui->pipe_config[1] != -1) close(c_ui->pipe_config[1]);
|
||||
}
|
||||
|
||||
if (uwsgi.vassals_stop_hook) {
|
||||
@@ -810,8 +812,9 @@ void emperor_del(struct uwsgi_instance *c_ui) {
|
||||
close(c_ui->on_demand_fd);
|
||||
}
|
||||
|
||||
free(c_ui);
|
||||
if (c_ui->use_config) free(c_ui->config);
|
||||
|
||||
free(c_ui);
|
||||
}
|
||||
|
||||
void emperor_back_to_ondemand(struct uwsgi_instance *c_ui) {
|
||||
@@ -1023,13 +1026,15 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
n_ui->pipe[0] = -1;
|
||||
n_ui->pipe[1] = -1;
|
||||
|
||||
n_ui->pipe_config[0] = -1;
|
||||
n_ui->pipe_config[1] = -1;
|
||||
|
||||
// ok here we check if we need to bind to the specified socket or continue with the activation
|
||||
if (socket_name) {
|
||||
n_ui->on_demand_fd = on_demand_bind(socket_name);
|
||||
if (n_ui->on_demand_fd < 0) {
|
||||
uwsgi_error("emperor_add()/bind()");
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
emperor_del(n_ui);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1040,8 +1045,7 @@ void emperor_add(struct uwsgi_emperor_scanner *ues, char *name, time_t born, cha
|
||||
|
||||
if (uwsgi_emperor_vassal_start(n_ui)) {
|
||||
// clear the vassal
|
||||
free(n_ui);
|
||||
c_ui->ui_next = NULL;
|
||||
emperor_del(n_ui);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1136,7 +1140,7 @@ static pid_t emperor_connect_to_fork_server(char *socket, struct uwsgi_instance
|
||||
if (ret) {
|
||||
free(buf);
|
||||
uwsgi_log_verbose("[uwsgi-emperor] %s: unable to complete fork-server session\n", n_ui->name);
|
||||
goto end;
|
||||
goto end2;
|
||||
}
|
||||
|
||||
pid_t pid = -1;
|
||||
@@ -1151,6 +1155,7 @@ static pid_t emperor_connect_to_fork_server(char *socket, struct uwsgi_instance
|
||||
|
||||
end:
|
||||
uwsgi_buffer_destroy(ub);
|
||||
end2:
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
@@ -1184,6 +1189,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
// a new uWSGI instance will start
|
||||
if (uwsgi.emperor_use_fork_server) {
|
||||
// pid can only be > 0 or -1
|
||||
n_ui->adopted = 1;
|
||||
pid = emperor_connect_to_fork_server(uwsgi.emperor_use_fork_server, n_ui);
|
||||
}
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL) && !defined(__ia64__)
|
||||
@@ -1203,6 +1209,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
n_ui->pid = pid;
|
||||
// close the right side of the pipe
|
||||
close(n_ui->pipe[1]);
|
||||
n_ui->pipe[1] = -1;
|
||||
/* THE ON-DEMAND file descriptor is left mapped to the emperor to allow fast-respawn
|
||||
// TODO add an option to force closing it
|
||||
// close the "on demand" socket
|
||||
@@ -1213,6 +1220,7 @@ int uwsgi_emperor_vassal_start(struct uwsgi_instance *n_ui) {
|
||||
*/
|
||||
if (n_ui->use_config) {
|
||||
close(n_ui->pipe_config[1]);
|
||||
n_ui->pipe_config[1] = -1;
|
||||
}
|
||||
|
||||
if (n_ui->use_config) {
|
||||
@@ -1967,7 +1975,7 @@ recheck:
|
||||
has_children = 0;
|
||||
while (ui_current->ui_next) {
|
||||
ui_current = ui_current->ui_next;
|
||||
if (ui_current->pid > -1) {
|
||||
if (ui_current->pid > -1 && !ui_current->adopted) {
|
||||
has_children++;
|
||||
}
|
||||
}
|
||||
@@ -2189,6 +2197,9 @@ void emperor_send_stats(int fd) {
|
||||
if (uwsgi_stats_keyval_comma(us, "on_demand", c_ui->socket_name ? c_ui->socket_name : ""))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "adopted", (unsigned long long) c_ui->adopted))
|
||||
goto end0;
|
||||
|
||||
if (uwsgi_stats_keylong_comma(us, "uid", (unsigned long long) c_ui->uid))
|
||||
goto end0;
|
||||
if (uwsgi_stats_keylong_comma(us, "gid", (unsigned long long) c_ui->gid))
|
||||
@@ -2292,9 +2303,11 @@ end:
|
||||
void uwsgi_emperor_start() {
|
||||
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0)) {
|
||||
uwsgi_error("uwsgi_fork_server()/fork()");
|
||||
exit(1);
|
||||
if (uwsgi.emperor_use_fork_server) {
|
||||
if (prctl(PR_SET_CHILD_SUBREAPER, 1, 0, 0, 0)) {
|
||||
uwsgi_error("uwsgi_fork_server()/fork()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -2548,6 +2561,7 @@ static void emperor_notify_ready() {
|
||||
char byte = 1;
|
||||
if (write(uwsgi.emperor_fd, &byte, 1) != 1) {
|
||||
uwsgi_error("emperor_notify_ready()/write()");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+68
-15
@@ -14,6 +14,11 @@ from now on, we can consider the new child as a full-featured vassal
|
||||
|
||||
*/
|
||||
|
||||
static void parse_argv_hook(uint16_t item, char *value, uint16_t vlen, void *data) {
|
||||
struct uwsgi_string_list **usl = (struct uwsgi_string_list **) data;
|
||||
uwsgi_string_new_list(usl, uwsgi_concat2n(value, vlen, "", 0));
|
||||
}
|
||||
|
||||
void uwsgi_fork_server(char *socket) {
|
||||
// map fd 0 to /dev/null to avoid mess
|
||||
uwsgi_remap_fd(0, "/dev/null");
|
||||
@@ -33,23 +38,52 @@ void uwsgi_fork_server(char *socket) {
|
||||
uwsgi_error("uwsgi_fork_server()/accept()");
|
||||
continue;
|
||||
}
|
||||
char buf[4096];
|
||||
char hbuf[4];
|
||||
pid_t ppid = -1;
|
||||
uid_t uid = -1;
|
||||
gid_t gid = -1;
|
||||
int fds_count = 0;
|
||||
int fds_count = 8;
|
||||
size_t remains = 4;
|
||||
// we can receive upto 8 fds (generally from 1 to 3)
|
||||
int fds[8];
|
||||
ssize_t len = uwsgi_recv_cred_and_fds(client_fd, buf, 4096, &ppid, &uid, &gid, fds, &fds_count);
|
||||
uwsgi_log("RET = %d %d %d %d\n", len, ppid, uid, gid);
|
||||
// we only read 4 bytes header
|
||||
ssize_t len = uwsgi_recv_cred_and_fds(client_fd, hbuf, remains, &ppid, &uid, &gid, fds, &fds_count);
|
||||
uwsgi_log("RET = %d %d %d %d fds:%d\n", len, ppid, uid, gid, fds_count);
|
||||
if (len <= 0) {
|
||||
uwsgi_error("uwsgi_fork_server()/recvmsg()");
|
||||
goto end;
|
||||
}
|
||||
remains -= len;
|
||||
|
||||
if (uwsgi_read_nb(client_fd, hbuf + (4-remains), remains, uwsgi.socket_timeout)) {
|
||||
uwsgi_error("uwsgi_fork_server()/uwsgi_read_nb()");
|
||||
goto end;
|
||||
}
|
||||
|
||||
struct uwsgi_header *uh = (struct uwsgi_header *) hbuf;
|
||||
// this memory area must be freed in the right place !!!
|
||||
char *body_argv = uwsgi_malloc(uh->pktsize);
|
||||
if (uwsgi_read_nb(client_fd, body_argv, uh->pktsize, uwsgi.socket_timeout)) {
|
||||
free(body_argv);
|
||||
uwsgi_error("uwsgi_fork_server()/uwsgi_read_nb()");
|
||||
goto end;
|
||||
}
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
free(body_argv);
|
||||
// close inherited decriptors excluded the passed fds and client_fd
|
||||
int i;
|
||||
for(i=0;i<fds_count;i++) close(fds[i]);
|
||||
// error on fork()
|
||||
uwsgi_error("uwsgi_fork_server()/fork()");
|
||||
goto end;
|
||||
}
|
||||
else if (pid > 0) {
|
||||
free(body_argv);
|
||||
// close inherited decriptors excluded the passed fds and client_fd
|
||||
int i;
|
||||
for(i=0;i<fds_count;i++) close(fds[i]);
|
||||
// wait for child death...
|
||||
waitpid(pid, NULL, 0);
|
||||
goto end;
|
||||
@@ -57,6 +91,12 @@ void uwsgi_fork_server(char *socket) {
|
||||
else {
|
||||
// close everything excluded the passed fds and client_fd
|
||||
// set EMPEROR_FD and FD_CONFIG env vars
|
||||
char *uef = uwsgi_num2str(fds[0]);
|
||||
if (setenv("UWSGI_EMPEROR_FD", uef, 1)) {
|
||||
uwsgi_error("setenv()");
|
||||
exit(1);
|
||||
}
|
||||
free(uef);
|
||||
// dup the on_demand socket to 0 and close it
|
||||
|
||||
// now fork again and die
|
||||
@@ -70,26 +110,39 @@ void uwsgi_fork_server(char *socket) {
|
||||
}
|
||||
else {
|
||||
// send the pid to the client_fd and close it
|
||||
struct uwsgi_buffer *ub = uwsgi_buffer_new(uwsgi.page_size);
|
||||
// leave space for header
|
||||
ub->pos = 4;
|
||||
if (uwsgi_buffer_append_keynum(ub, "pid", 3, getppid())) exit(1);
|
||||
// fix uwsgi header
|
||||
if (uwsgi_buffer_set_uh(ub, 35, 0)) goto end;
|
||||
// send_pid()
|
||||
if (uwsgi_write_nb(client_fd, ub->buf, ub->pos, uwsgi.socket_timeout)) exit(1);
|
||||
close(client_fd);
|
||||
uwsgi_log("double fork() and reparenting successfull (new pid: %d)\n", getpid());
|
||||
|
||||
|
||||
// now parse the uwsgi packet array and build the argv
|
||||
uwsgi.new_argc = 6;
|
||||
// we do not free old uwsgi.argv as it could contains still used pointers
|
||||
uwsgi_log("%s\n", uwsgi.binary_path);
|
||||
uwsgi.new_argv = uwsgi_malloc(sizeof(char *) * (uwsgi.argc+1));
|
||||
uwsgi.new_argv[0] = uwsgi.binary_path;
|
||||
uwsgi.new_argv[1] = uwsgi_str("--http-socket");
|
||||
uwsgi.new_argv[2] = uwsgi_str(":1717");
|
||||
uwsgi.new_argv[3] = uwsgi_str("--master");
|
||||
uwsgi.new_argv[4] = uwsgi_str("--processes");
|
||||
uwsgi.new_argv[5] = uwsgi_str("8");
|
||||
uwsgi.new_argv[6] = NULL;
|
||||
struct uwsgi_string_list *usl = NULL, *usl_argv = NULL;
|
||||
uwsgi_hooked_parse_array(body_argv, uh->pktsize, parse_argv_hook, &usl_argv);
|
||||
free(body_argv);
|
||||
|
||||
// build new argc/argv
|
||||
uwsgi.new_argc = 0;
|
||||
uwsgi_foreach(usl, usl_argv) {
|
||||
uwsgi.new_argc++;
|
||||
}
|
||||
|
||||
uwsgi.new_argv = uwsgi_calloc(sizeof(char *) * (uwsgi.new_argc + 1));
|
||||
int counter = 0;
|
||||
uwsgi_foreach(usl, usl_argv) {
|
||||
uwsgi.new_argv[counter] = usl->value;
|
||||
counter++;
|
||||
}
|
||||
// this is the only step required to have a consistent environment
|
||||
uwsgi.fork_socket = NULL;
|
||||
// fixup the Emperor communication
|
||||
uwsgi_check_emperor();
|
||||
// continue with uWSGI startup
|
||||
return;
|
||||
}
|
||||
|
||||
+3
-3
@@ -292,9 +292,9 @@ void uwsgi_commandline_config() {
|
||||
uwsgi_log("optind:%d argc:%d\n", optind, uwsgi.argc);
|
||||
#endif
|
||||
|
||||
if (optind < uwsgi.argc) {
|
||||
for (i = optind; i < uwsgi.argc; i++) {
|
||||
char *lazy = uwsgi.argv[i];
|
||||
if (optind < argc) {
|
||||
for (i = optind; i < argc; i++) {
|
||||
char *lazy = argv[i];
|
||||
if (lazy[0] != '[') {
|
||||
uwsgi_opt_load(NULL, lazy, NULL);
|
||||
// manage magic mountpoint
|
||||
|
||||
@@ -1519,9 +1519,11 @@ ssize_t uwsgi_recv_cred_and_fds(int fd, char *buf, size_t buf_len, pid_t *pid, u
|
||||
|
||||
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
|
||||
while(cmsg) {
|
||||
uwsgi_log("ROUND ROUND\n");
|
||||
if (cmsg->cmsg_level != SOL_SOCKET) goto next;
|
||||
if (cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
size_t fds_len = cmsg->cmsg_len - ((char *) CMSG_DATA(cmsg) - (char *) cmsg);
|
||||
uwsgi_log("FDS_LEN = %d\n", fds_len);
|
||||
memcpy(fds, CMSG_DATA(cmsg), fds_len);
|
||||
*fds_count = fds_len/sizeof(int);
|
||||
}
|
||||
|
||||
@@ -223,6 +223,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
#if defined(__linux__) && !defined(OBSOLETE_LINUX_KERNEL)
|
||||
{"emperor-use-clone", required_argument, 0, "use clone() instead of fork() passing the specified unshare() flags", uwsgi_opt_set_unshare, &uwsgi.emperor_clone, 0},
|
||||
#endif
|
||||
{"emperor-use-fork-server", required_argument, 0, "connect to the specified fork server instead of using plain fork() for new vassals", uwsgi_opt_set_str, &uwsgi.emperor_use_fork_server, 0},
|
||||
#ifdef UWSGI_CAP
|
||||
{"emperor-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0},
|
||||
{"vassals-cap", required_argument, 0, "set vassals capability", uwsgi_opt_set_emperor_cap, NULL, 0},
|
||||
|
||||
Reference in New Issue
Block a user