summaryrefslogtreecommitdiff
path: root/core/fork_server.c
diff options
context:
space:
mode:
authorUnbit <info@unbit.it>2014-05-06 17:28:39 +0200
committerUnbit <info@unbit.it>2014-05-06 17:28:39 +0200
commit1219f6fc302193179d63551ae22c2300f323b4f0 (patch)
treecd24088652c51bb3ce69cddf4e36910ce0dc1cec /core/fork_server.c
parent338700e95021a8c4f706ff1beeb5426f3f128c15 (diff)
downloaduwsgi-1219f6fc302193179d63551ae22c2300f323b4f0.tar.gz
added adopted-vassals concept
Diffstat (limited to 'core/fork_server.c')
-rw-r--r--core/fork_server.c85
1 files changed, 69 insertions, 16 deletions
diff --git a/core/fork_server.c b/core/fork_server.c
index ab4852ef..1c452f1e 100644
--- a/core/fork_server.c
+++ b/core/fork_server.c
@@ -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;
}