diff --git a/core/emperor.c b/core/emperor.c index 0a69dd34..abbccf71 100644 --- a/core/emperor.c +++ b/core/emperor.c @@ -1598,6 +1598,14 @@ static void uwsgi_emperor_spawn_vassal(struct uwsgi_instance *n_ui) { func(n_ui->name, n_ui->uid, n_ui->gid); } + char *force_chdir = vassal_attr_get(n_ui, uwsgi.emperor_chdir_attr); + if (force_chdir) { + if (chdir(force_chdir)) { + uwsgi_error("--emperor-chdir-attr/chdir()"); + exit(UWSGI_EXILE_CODE); + } + } + // start !!! if (execvp(vassal_argv[0], vassal_argv)) { uwsgi_error("execvp()"); diff --git a/core/uwsgi.c b/core/uwsgi.c index 5842b1d6..ecf04c6a 100644 --- a/core/uwsgi.c +++ b/core/uwsgi.c @@ -236,7 +236,8 @@ static struct uwsgi_option uwsgi_base_options[] = { {"emperor-collect-attribute", required_argument, 0, "collect the specified vassal attribute from imperial monitors", uwsgi_opt_add_string_list, &uwsgi.emperor_collect_attributes, 0}, {"emperor-collect-attr", required_argument, 0, "collect the specified vassal attribute from imperial monitors", uwsgi_opt_add_string_list, &uwsgi.emperor_collect_attributes, 0}, {"emperor-fork-server-attr", required_argument, 0, "set teh vassal's attribute to get when checking for fork-server", uwsgi_opt_set_str, &uwsgi.emperor_fork_server_attr, 0}, - {"emperor-wrapper-attr", required_argument, 0, "set teh vassal's attribute to get when checking for fork-wrapper", uwsgi_opt_set_str, &uwsgi.emperor_wrapper_attr, 0}, + {"emperor-wrapper-attr", required_argument, 0, "set the vassal's attribute to get when checking for fork-wrapper", uwsgi_opt_set_str, &uwsgi.emperor_wrapper_attr, 0}, + {"emperor-chdir-attr", required_argument, 0, "set the vassal's attribute to get when checking for chdir", uwsgi_opt_set_str, &uwsgi.emperor_chdir_attr, 0}, {"imperial-monitor-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0}, {"imperial-monitors-list", no_argument, 0, "list enabled imperial monitors", uwsgi_opt_true, &uwsgi.imperial_monitor_list, 0}, {"vassals-inherit", required_argument, 0, "add config templates to vassals config (uses --inherit)", uwsgi_opt_add_string_list, &uwsgi.vassals_templates, 0}, diff --git a/plugins/python/python_plugin.c b/plugins/python/python_plugin.c index f3e7c073..e82ac552 100644 --- a/plugins/python/python_plugin.c +++ b/plugins/python/python_plugin.c @@ -63,6 +63,29 @@ void uwsgi_opt_pyver(char *opt, char *foo, void *bar) { exit(0); } +int uwsgi_python_init(void); +void uwsgi_python_preinit_apps(void); +static void uwsgi_early_python(char *opt, char *foo, void *bar) { + static int early_initialized = 0; + if (early_initialized) return; + early_initialized = 1; + uwsgi_python_init(); + uwsgi_python_preinit_apps(); +} + + +static void uwsgi_early_python_import(char *opt, char *module, void *bar) { + uwsgi_early_python(opt, NULL, NULL); + if (strchr(module, '/') || uwsgi_endswith(module, ".py")) { + uwsgi_pyimport_by_filename(uwsgi_pythonize(module), module); + } + else { + if (PyImport_ImportModule(module) == NULL) { + PyErr_Print(); + } + } +} + void uwsgi_opt_ini_paste(char *opt, char *value, void *foobar) { @@ -170,6 +193,10 @@ struct uwsgi_option uwsgi_python_options[] = { {"py-call-osafterfork", no_argument, 0, "enable child processes running cpython to trap OS signals", uwsgi_opt_true, &up.call_osafterfork, 0}, + {"early-python", no_argument, 0, "load the python VM as soon as possible (useful for the fork server)", uwsgi_early_python, NULL, UWSGI_OPT_IMMEDIATE}, + {"early-pyimport", required_argument, 0, "import a python module in the early phase", uwsgi_early_python_import, NULL, UWSGI_OPT_IMMEDIATE}, + {"early-python-import", required_argument, 0, "import a python module in the early phase", uwsgi_early_python_import, NULL, UWSGI_OPT_IMMEDIATE}, + {0, 0, 0, 0, 0, 0, 0}, }; @@ -1037,6 +1064,10 @@ void uwsgi_python_destroy_env_holy(struct wsgi_request *wsgi_req) { // this hook will be executed by master (or worker1 when master is not requested, so COW is in place) void uwsgi_python_preinit_apps() { + struct uwsgi_string_list *upli = up.shared_import_list; + + if (up.pre_initialized) goto ready; + up.pre_initialized = 1; init_pyargv(); @@ -1068,8 +1099,9 @@ void uwsgi_python_preinit_apps() { init_uwsgi_vars(); +ready: + // load shared imports - struct uwsgi_string_list *upli = up.shared_import_list; while(upli) { if (strchr(upli->value, '/') || uwsgi_endswith(upli->value, ".py")) { uwsgi_pyimport_by_filename(uwsgi_pythonize(upli->value), upli->value); diff --git a/plugins/python/uwsgi_python.h b/plugins/python/uwsgi_python.h index a2cc6e69..e33c14a7 100644 --- a/plugins/python/uwsgi_python.h +++ b/plugins/python/uwsgi_python.h @@ -199,6 +199,7 @@ struct uwsgi_python { struct uwsgi_string_list *sharedarea; int call_osafterfork; + int pre_initialized; }; diff --git a/uwsgi.h b/uwsgi.h index d3c35cac..b8d26f76 100644 --- a/uwsgi.h +++ b/uwsgi.h @@ -2736,6 +2736,7 @@ struct uwsgi_server { int emperor_subreaper; struct uwsgi_string_list *hook_as_on_demand_vassal; uint64_t max_requests_delta; + char *emperor_chdir_attr; }; struct uwsgi_rpc {