mirror of
https://github.com/clearlinux/uwsgi.git
synced 2026-08-19 03:57:21 +00:00
first prototype of a fork server
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
#include <uwsgi.h>
|
||||
|
||||
extern struct uwsgi_server uwsgi;
|
||||
|
||||
void uwsgi_fork_server(char *socket) {
|
||||
int fd = bind_to_unix(socket, uwsgi.listen_queue, uwsgi.chmod_socket, uwsgi.abstract_socket);
|
||||
if (fd < 0) exit(1);
|
||||
|
||||
if (uwsgi_socket_passcred(fd)) exit(1);
|
||||
|
||||
for(;;) {
|
||||
struct sockaddr_un client_src;
|
||||
socklen_t client_src_len = 0;
|
||||
int client_fd = accept(fd, (struct sockaddr *) &client_src, &client_src_len);
|
||||
if (client_fd < 0) {
|
||||
uwsgi_error("uwsgi_fork_server()/accept()");
|
||||
continue;
|
||||
}
|
||||
char buf[4096];
|
||||
pid_t ppid = -1;
|
||||
uid_t uid = -1;
|
||||
gid_t gid = -1;
|
||||
ssize_t len = uwsgi_recv_cred2(client_fd, buf, 4096, &ppid, &uid, &gid);
|
||||
uwsgi_log("RET = %d %d %d %d\n", len, ppid, uid, gid);
|
||||
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
uwsgi_error("uwsgi_fork_server()/fork()");
|
||||
goto end;
|
||||
}
|
||||
else if (pid > 0) {
|
||||
goto end;
|
||||
}
|
||||
else {
|
||||
// reparent the process
|
||||
#ifdef __linux__
|
||||
if (prctl(PR_SET_CHILD_SUBREAPER, ppid, 0, 0, 0)) {
|
||||
uwsgi_error("uwsgi_fork_server()/fork()");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
// now fork again and kill
|
||||
pid_t new_pid = fork();
|
||||
if (new_pid < 0) {
|
||||
uwsgi_error("uwsgi_fork_server()/fork()");
|
||||
exit(1);
|
||||
}
|
||||
else if (new_pid > 0) {
|
||||
exit(0);
|
||||
}
|
||||
else {
|
||||
uwsgi_log("double fork() and reparenting successfull (new pid: %d)\n", getpid());
|
||||
uwsgi.argc = 3;
|
||||
uwsgi.argv = uwsgi_malloc(sizeof(char *) * (uwsgi.argc+1));
|
||||
uwsgi.argv[0] = uwsgi.binary_path;
|
||||
uwsgi.argv[1] = uwsgi_str("--socket");
|
||||
uwsgi.argv[2] = uwsgi_str(":1717");
|
||||
uwsgi.argv[3] = NULL;
|
||||
// this is the only step required to have a consistent environment
|
||||
uwsgi.fork_socket = NULL;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
close(client_fd);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -252,6 +252,8 @@ void uwsgi_commandline_config() {
|
||||
int i;
|
||||
|
||||
uwsgi.option_index = -1;
|
||||
// required in case we want to call getopt_long from the beginning
|
||||
optind = 0;
|
||||
|
||||
char *optname;
|
||||
while ((i = getopt_long(uwsgi.argc, uwsgi.argv, uwsgi.short_options, uwsgi.long_options, &uwsgi.option_index)) != -1) {
|
||||
|
||||
@@ -356,6 +356,7 @@ static struct uwsgi_option uwsgi_base_options[] = {
|
||||
{"setns-skip", required_argument, 0, "skip the specified entry when sending setns file descriptors", uwsgi_opt_add_string_list, &uwsgi.setns_socket_skip, 0},
|
||||
{"setns", required_argument, 0, "join a namespace created by an external uWSGI instance", uwsgi_opt_set_str, &uwsgi.setns, 0},
|
||||
{"setns-preopen", no_argument, 0, "open /proc/self/ns as soon as possible and cache fds", uwsgi_opt_true, &uwsgi.setns_preopen, 0},
|
||||
{"fork-socket", required_argument, 0, "suspend the execution after early initialization and fork() at every unix socket connection", uwsgi_opt_set_str, &uwsgi.fork_socket, 0},
|
||||
#endif
|
||||
{"jailed", no_argument, 0, "mark the instance as jailed (force the execution of post_jail hooks)", uwsgi_opt_true, &uwsgi.jailed, 0},
|
||||
#if defined(__FreeBSD__) || defined(__GNU_kFreeBSD__)
|
||||
@@ -2131,6 +2132,8 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
struct group *gr = getgrgid(getgid());
|
||||
uwsgi.magic_table['G'] = gr ? gr->gr_name : uwsgi.magic_table['g'];
|
||||
|
||||
configure:
|
||||
|
||||
// you can embed a ini file in the uWSGi binary with default options
|
||||
#ifdef UWSGI_EMBED_CONFIG
|
||||
uwsgi_ini_config("", uwsgi.magic_table);
|
||||
@@ -2155,6 +2158,14 @@ void uwsgi_setup(int argc, char *argv[], char *envp[]) {
|
||||
// ok, the options dictionary is available, lets manage it
|
||||
uwsgi_configure();
|
||||
|
||||
// stop the execution until a connection arrives on the fork socket
|
||||
if (uwsgi.fork_socket) {
|
||||
uwsgi_log_verbose("waiting for fork-socket connections...\n");
|
||||
uwsgi_fork_server(uwsgi.fork_socket);
|
||||
// if we are here a new process has been spawned
|
||||
goto configure;
|
||||
}
|
||||
|
||||
// fixup cwd
|
||||
if (uwsgi.force_cwd) uwsgi.cwd = uwsgi.force_cwd;
|
||||
|
||||
|
||||
@@ -67,6 +67,8 @@ struct uwsgi_perl {
|
||||
CV *spooler;
|
||||
|
||||
int no_plack;
|
||||
|
||||
void *early_psgi_callable;
|
||||
};
|
||||
|
||||
void init_perl_embedded_module(void);
|
||||
|
||||
@@ -453,6 +453,12 @@ int init_psgi_app(struct wsgi_request *wsgi_req, char *app, uint16_t app_len, Pe
|
||||
PERL_SET_CONTEXT(interpreters[0]);
|
||||
}
|
||||
|
||||
// is it an early loading ?
|
||||
if (!uwsgi.workers) {
|
||||
uperl.early_psgi_callable = callables[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
@@ -26,6 +26,12 @@ static void uwsgi_opt_plshell(char *opt, char *value, void *foobar) {
|
||||
}
|
||||
}
|
||||
|
||||
int uwsgi_perl_init(void);
|
||||
static void uwsgi_opt_early_psgi(char *opt, char *value, void *foobar) {
|
||||
uwsgi_perl_init();
|
||||
init_psgi_app(NULL, value, strlen(value), uperl.main);
|
||||
}
|
||||
|
||||
struct uwsgi_option uwsgi_perl_options[] = {
|
||||
|
||||
{"psgi", required_argument, 0, "load a psgi app", uwsgi_opt_set_str, &uperl.psgi, 0},
|
||||
@@ -46,6 +52,7 @@ struct uwsgi_option uwsgi_perl_options[] = {
|
||||
{"plshell-oneshot", no_argument, 0, "run a perl interactive shell (one shot)", uwsgi_opt_plshell, NULL, 0},
|
||||
|
||||
{"perl-no-plack", no_argument, 0, "force the use of do instead of Plack::Util::load_psgi", uwsgi_opt_true, &uperl.no_plack, 0},
|
||||
{"early-psgi", required_argument, 0, "load a psgi app soon after perl initialization", uwsgi_opt_early_psgi, NULL, UWSGI_OPT_IMMEDIATE},
|
||||
{0, 0, 0, 0, 0, 0, 0},
|
||||
|
||||
};
|
||||
@@ -437,6 +444,9 @@ int uwsgi_perl_init(){
|
||||
int argc;
|
||||
int i;
|
||||
|
||||
// the perl interpreter could be already initialized
|
||||
if (uperl.main) return 0;
|
||||
|
||||
uperl.embedding[0] = "";
|
||||
uperl.embedding[1] = "-e";
|
||||
uperl.embedding[2] = "0";
|
||||
|
||||
@@ -2709,6 +2709,8 @@ struct uwsgi_server {
|
||||
|
||||
int mule_reload_mercy;
|
||||
int alarm_cheap;
|
||||
|
||||
char *fork_socket;
|
||||
};
|
||||
|
||||
struct uwsgi_rpc {
|
||||
@@ -4761,6 +4763,8 @@ mode_t uwsgi_mode_t(char *, int *);
|
||||
int uwsgi_notify_socket_manage(int);
|
||||
int uwsgi_notify_msg(char *, char *, size_t);
|
||||
|
||||
void uwsgi_fork_server(char *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -602,7 +602,7 @@ class uConf(object):
|
||||
'core/setup_utils', 'core/clock', 'core/init', 'core/buffer', 'core/reader', 'core/writer', 'core/alarm', 'core/cron', 'core/hooks',
|
||||
'core/plugins', 'core/lock', 'core/cache', 'core/daemons', 'core/errors', 'core/hash', 'core/master_events', 'core/chunked',
|
||||
'core/queue', 'core/event', 'core/signal', 'core/strings', 'core/progress', 'core/timebomb', 'core/ini', 'core/fsmon', 'core/mount',
|
||||
'core/metrics', 'core/plugins_builder', 'core/sharedarea',
|
||||
'core/metrics', 'core/plugins_builder', 'core/sharedarea', 'core/fork_server',
|
||||
'core/rpc', 'core/gateway', 'core/loop', 'core/cookie', 'core/querystring', 'core/rb_timers', 'core/transformations', 'core/uwsgi']
|
||||
# add protocols
|
||||
self.gcc_list.append('proto/base')
|
||||
|
||||
Reference in New Issue
Block a user