summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorTiago Natel de Moura <t.nateldemoura@f5.com>2020-03-09 16:28:25 +0000
committerTiago Natel de Moura <t.nateldemoura@f5.com>2020-03-09 16:28:25 +0000
commite9e5ddd5a5d9ce99768833137eac2551a710becf (patch)
tree940e591004b16216d5122cd12b367f3ebf15e0d3 /src
parentaacf11152c314efb1895b6d44ba72dc9f1801c7d (diff)
downloadunit-e9e5ddd5a5d9ce99768833137eac2551a710becf.tar.gz
unit-e9e5ddd5a5d9ce99768833137eac2551a710becf.tar.bz2
Refactor of process management.
The process abstraction has changed to: setup(task, process) start(task, process_data) prefork(task, process, mp) The prefork() occurs in the main process right before fork. The file src/nxt_main_process.c is completely free of process specific logic. The creation of a process now supports a PROCESS_CREATED state. The The setup() function of each process can set its state to either created or ready. If created, a MSG_PROCESS_CREATED is sent to main process, where external setup can be done (required for rootfs under container). The core processes (discovery, controller and router) doesn't need external setup, then they all proceeds to their start() function straight away. In the case of applications, the load of the module happens at the process setup() time and The module's init() function has changed to be the start() of the process. The module API has changed to: setup(task, process, conf) start(task, data) As a direct benefit of the PROCESS_CREATED message, the clone(2) of processes using pid namespaces now doesn't need to create a pipe to make the child block until parent setup uid/gid mappings nor it needs to receive the child pid.
Diffstat (limited to 'src')
-rw-r--r--src/nxt_application.c363
-rw-r--r--src/nxt_application.h11
-rw-r--r--src/nxt_cert.c11
-rw-r--r--src/nxt_cert.h2
-rw-r--r--src/nxt_clone.h14
-rw-r--r--src/nxt_controller.c142
-rw-r--r--src/nxt_external.c11
-rw-r--r--src/nxt_java.c61
-rw-r--r--src/nxt_main_process.c1049
-rw-r--r--src/nxt_main_process.h19
-rw-r--r--src/nxt_php_sapi.c32
-rw-r--r--src/nxt_port.c4
-rw-r--r--src/nxt_port.h141
-rw-r--r--src/nxt_port_memory.c2
-rw-r--r--src/nxt_process.c534
-rw-r--r--src/nxt_process.h137
-rw-r--r--src/nxt_process_type.h2
-rw-r--r--src/nxt_python_wsgi.c13
-rw-r--r--src/nxt_router.c44
-rw-r--r--src/nxt_runtime.c60
-rw-r--r--src/nxt_runtime.h1
-rw-r--r--src/nxt_signal_handlers.c67
-rw-r--r--src/nxt_unit.c2
-rw-r--r--src/nxt_worker_process.c118
-rw-r--r--src/perl/nxt_perl_psgi.c11
-rw-r--r--src/ruby/nxt_ruby.c20
26 files changed, 1541 insertions, 1330 deletions
diff --git a/src/nxt_application.c b/src/nxt_application.c
index bebe3907..6de82257 100644
--- a/src/nxt_application.c
+++ b/src/nxt_application.c
@@ -25,6 +25,8 @@ typedef struct {
} nxt_module_t;
+static nxt_int_t nxt_discovery_start(nxt_task_t *task,
+ nxt_process_data_t *data);
static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path);
static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp,
nxt_array_t *modules, const char *name);
@@ -34,7 +36,27 @@ static void nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg,
void *data);
static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task,
const char *name);
+static nxt_int_t nxt_app_prefork(nxt_task_t *task, nxt_process_t *process,
+ nxt_mp_t *mp);
+static nxt_int_t nxt_app_setup(nxt_task_t *task, nxt_process_t *process);
static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment);
+static nxt_int_t nxt_app_isolation(nxt_task_t *task,
+ nxt_conf_value_t *isolation, nxt_process_t *process);
+
+#if (NXT_HAVE_CLONE)
+static nxt_int_t nxt_app_clone_flags(nxt_task_t *task,
+ nxt_conf_value_t *namespaces, nxt_clone_t *clone);
+#endif
+
+#if (NXT_HAVE_CLONE_NEWUSER)
+static nxt_int_t nxt_app_isolation_creds(nxt_task_t *task,
+ nxt_conf_value_t *isolation, nxt_process_t *process);
+static nxt_int_t nxt_app_isolation_credential_map(nxt_task_t *task,
+ nxt_mp_t *mem_pool, nxt_conf_value_t *map_array,
+ nxt_clone_credential_map_t *map);
+#endif
+
+nxt_str_t nxt_server = nxt_string(NXT_SERVER);
static uint32_t compat[] = {
@@ -42,14 +64,53 @@ static uint32_t compat[] = {
};
-nxt_str_t nxt_server = nxt_string(NXT_SERVER);
+static nxt_app_module_t *nxt_app;
-static nxt_app_module_t *nxt_app;
+static const nxt_port_handlers_t nxt_discovery_process_port_handlers = {
+ .quit = nxt_signal_quit_handler,
+ .new_port = nxt_port_new_port_handler,
+ .change_file = nxt_port_change_log_file_handler,
+ .mmap = nxt_port_mmap_handler,
+ .data = nxt_port_data_handler,
+ .remove_pid = nxt_port_remove_pid_handler,
+ .rpc_ready = nxt_port_rpc_handler,
+ .rpc_error = nxt_port_rpc_handler,
+};
-nxt_int_t
-nxt_discovery_start(nxt_task_t *task, void *data)
+static const nxt_port_handlers_t nxt_app_process_port_handlers = {
+ .quit = nxt_signal_quit_handler,
+ .rpc_ready = nxt_port_rpc_handler,
+ .rpc_error = nxt_port_rpc_handler,
+};
+
+
+const nxt_process_init_t nxt_discovery_process = {
+ .name = "discovery",
+ .type = NXT_PROCESS_DISCOVERY,
+ .prefork = NULL,
+ .restart = 0,
+ .setup = nxt_process_core_setup,
+ .start = nxt_discovery_start,
+ .port_handlers = &nxt_discovery_process_port_handlers,
+ .signals = nxt_process_signals,
+};
+
+
+const nxt_process_init_t nxt_app_process = {
+ .type = NXT_PROCESS_APP,
+ .setup = nxt_app_setup,
+ .prefork = nxt_app_prefork,
+ .restart = 0,
+ .start = NULL, /* set to module->start */
+ .port_handlers = &nxt_app_process_port_handlers,
+ .signals = nxt_process_signals,
+};
+
+
+static nxt_int_t
+nxt_discovery_start(nxt_task_t *task, nxt_process_data_t *data)
{
uint32_t stream;
nxt_buf_t *b;
@@ -57,7 +118,7 @@ nxt_discovery_start(nxt_task_t *task, void *data)
nxt_port_t *main_port, *discovery_port;
nxt_runtime_t *rt;
- nxt_debug(task, "DISCOVERY");
+ nxt_log(task, NXT_LOG_INFO, "discovery started");
rt = task->thread->runtime;
@@ -301,18 +362,85 @@ nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data)
static void
nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data)
{
- nxt_worker_process_quit_handler(task, msg);
+ nxt_signal_quit_handler(task, msg);
}
-nxt_int_t
-nxt_app_start(nxt_task_t *task, void *data)
+static nxt_int_t
+nxt_app_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
+{
+ nxt_int_t cap_setid;
+ nxt_int_t ret;
+ nxt_runtime_t *rt;
+ nxt_common_app_conf_t *app_conf;
+
+ rt = task->thread->runtime;
+ app_conf = process->data.app;
+ cap_setid = rt->capabilities.setid;
+
+ if (app_conf->isolation != NULL) {
+ ret = nxt_app_isolation(task, app_conf->isolation, process);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+ }
+
+#if (NXT_HAVE_CLONE_NEWUSER)
+ if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
+ cap_setid = 1;
+ }
+#endif
+
+ if (cap_setid) {
+ ret = nxt_process_creds_set(task, process, &app_conf->user,
+ &app_conf->group);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+
+ } else {
+ if (!nxt_str_eq(&app_conf->user, (u_char *) rt->user_cred.user,
+ nxt_strlen(rt->user_cred.user)))
+ {
+ nxt_alert(task, "cannot set user \"%V\" for app \"%V\": "
+ "missing capabilities", &app_conf->user, &app_conf->name);
+
+ return NXT_ERROR;
+ }
+
+ if (app_conf->group.length > 0
+ && !nxt_str_eq(&app_conf->group, (u_char *) rt->group,
+ nxt_strlen(rt->group)))
+ {
+ nxt_alert(task, "cannot set group \"%V\" for app \"%V\": "
+ "missing capabilities", &app_conf->group,
+ &app_conf->name);
+
+ return NXT_ERROR;
+ }
+ }
+
+#if (NXT_HAVE_CLONE_NEWUSER)
+ ret = nxt_process_vldt_isolation_creds(task, process);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return ret;
+ }
+#endif
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_app_setup(nxt_task_t *task, nxt_process_t *process)
{
nxt_int_t ret;
+ nxt_process_init_t *init;
nxt_app_lang_module_t *lang;
nxt_common_app_conf_t *app_conf;
- app_conf = data;
+ app_conf = process->data.app;
lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type);
if (nxt_slow_path(lang == NULL)) {
@@ -332,8 +460,8 @@ nxt_app_start(nxt_task_t *task, void *data)
}
}
- if (nxt_app->pre_init != NULL) {
- ret = nxt_app->pre_init(task, data);
+ if (nxt_app->setup != NULL) {
+ ret = nxt_app->setup(task, process, app_conf);
if (nxt_slow_path(ret != NXT_OK)) {
return ret;
@@ -360,16 +488,13 @@ nxt_app_start(nxt_task_t *task, void *data)
return NXT_ERROR;
}
- ret = nxt_app->init(task, data);
+ init = nxt_process_init(process);
- if (nxt_slow_path(ret != NXT_OK)) {
- nxt_debug(task, "application init failed");
+ init->start = nxt_app->start;
- } else {
- nxt_debug(task, "application init done");
- }
+ process->state = NXT_PROCESS_STATE_CREATED;
- return ret;
+ return NXT_OK;
}
@@ -429,6 +554,206 @@ nxt_app_set_environment(nxt_conf_value_t *environment)
}
+static nxt_int_t
+nxt_app_isolation(nxt_task_t *task, nxt_conf_value_t *isolation,
+ nxt_process_t *process)
+{
+#if (NXT_HAVE_CLONE)
+ nxt_int_t ret;
+ nxt_conf_value_t *obj;
+
+ static nxt_str_t nsname = nxt_string("namespaces");
+
+ obj = nxt_conf_get_object_member(isolation, &nsname, NULL);
+ if (obj != NULL) {
+ ret = nxt_app_clone_flags(task, obj, &process->isolation.clone);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+ }
+#endif
+
+#if (NXT_HAVE_CLONE_NEWUSER)
+ ret = nxt_app_isolation_creds(task, isolation, process);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+#endif
+
+ return NXT_OK;
+}
+
+
+#if (NXT_HAVE_CLONE_NEWUSER)
+
+static nxt_int_t
+nxt_app_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation,
+ nxt_process_t *process)
+{
+ nxt_int_t ret;
+ nxt_clone_t *clone;
+ nxt_conf_value_t *array;
+
+ static nxt_str_t uidname = nxt_string("uidmap");
+ static nxt_str_t gidname = nxt_string("gidmap");
+
+ clone = &process->isolation.clone;
+
+ array = nxt_conf_get_object_member(isolation, &uidname, NULL);
+ if (array != NULL) {
+ ret = nxt_app_isolation_credential_map(task, process->mem_pool, array,
+ &clone->uidmap);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+ }
+
+ array = nxt_conf_get_object_member(isolation, &gidname, NULL);
+ if (array != NULL) {
+ ret = nxt_app_isolation_credential_map(task, process->mem_pool, array,
+ &clone->gidmap);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_app_isolation_credential_map(nxt_task_t *task, nxt_mp_t *mp,
+ nxt_conf_value_t *map_array, nxt_clone_credential_map_t *map)
+{
+ nxt_int_t ret;
+ nxt_uint_t i;
+ nxt_conf_value_t *obj;
+
+ static nxt_conf_map_t nxt_clone_map_entry_conf[] = {
+ {
+ nxt_string("container"),
+ NXT_CONF_MAP_INT,
+ offsetof(nxt_clone_map_entry_t, container),
+ },
+
+ {
+ nxt_string("host"),
+ NXT_CONF_MAP_INT,
+ offsetof(nxt_clone_map_entry_t, host),
+ },
+
+ {
+ nxt_string("size"),
+ NXT_CONF_MAP_INT,
+ offsetof(nxt_clone_map_entry_t, size),
+ },
+ };
+
+ map->size = nxt_conf_array_elements_count(map_array);
+
+ if (map->size == 0) {
+ return NXT_OK;
+ }
+
+ map->map = nxt_mp_alloc(mp, map->size * sizeof(nxt_clone_map_entry_t));
+ if (nxt_slow_path(map->map == NULL)) {
+ return NXT_ERROR;
+ }
+
+ for (i = 0; i < map->size; i++) {
+ obj = nxt_conf_get_array_element(map_array, i);
+
+ ret = nxt_conf_map_object(mp, obj, nxt_clone_map_entry_conf,
+ nxt_nitems(nxt_clone_map_entry_conf),
+ map->map + i);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ nxt_alert(task, "clone map entry map error");
+ return NXT_ERROR;
+ }
+ }
+
+ return NXT_OK;
+}
+
+#endif
+
+#if (NXT_HAVE_CLONE)
+
+static nxt_int_t
+nxt_app_clone_flags(nxt_task_t *task, nxt_conf_value_t *namespaces,
+ nxt_clone_t *clone)
+{
+ uint32_t index;
+ nxt_str_t name;
+ nxt_int_t flag;
+ nxt_conf_value_t *value;
+
+ index = 0;
+
+ for ( ;; ) {
+ value = nxt_conf_next_object_member(namespaces, &name, &index);
+
+ if (value == NULL) {
+ break;
+ }
+
+ flag = 0;
+
+#if (NXT_HAVE_CLONE_NEWUSER)
+ if (nxt_str_eq(&name, "credential", 10)) {
+ flag = CLONE_NEWUSER;
+ }
+#endif
+
+#if (NXT_HAVE_CLONE_NEWPID)
+ if (nxt_str_eq(&name, "pid", 3)) {
+ flag = CLONE_NEWPID;
+ }
+#endif
+
+#if (NXT_HAVE_CLONE_NEWNET)
+ if (nxt_str_eq(&name, "network", 7)) {
+ flag = CLONE_NEWNET;
+ }
+#endif
+
+#if (NXT_HAVE_CLONE_NEWUTS)
+ if (nxt_str_eq(&name, "uname", 5)) {
+ flag = CLONE_NEWUTS;
+ }
+#endif
+
+#if (NXT_HAVE_CLONE_NEWNS)
+ if (nxt_str_eq(&name, "mount", 5)) {
+ flag = CLONE_NEWNS;
+ }
+#endif
+
+#if (NXT_HAVE_CLONE_NEWCGROUP)
+ if (nxt_str_eq(&name, "cgroup", 6)) {
+ flag = CLONE_NEWCGROUP;
+ }
+#endif
+
+ if (!flag) {
+ nxt_alert(task, "unknown namespace flag: \"%V\"", &name);
+ return NXT_ERROR;
+ }
+
+ if (nxt_conf_get_boolean(value)) {
+ clone->flags |= flag;
+ }
+ }
+
+ return NXT_OK;
+}
+
+#endif
+
+
+
nxt_app_lang_module_t *
nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name)
{
@@ -539,7 +864,7 @@ nxt_unit_default_init(nxt_task_t *task, nxt_unit_init_t *init)
nxt_fd_blocking(task, main_port->pair[1]);
- init->ready_stream = my_port->process->init->stream;
+ init->ready_stream = my_port->process->stream;
init->read_port.id.pid = my_port->pid;
init->read_port.id.id = my_port->id;
diff --git a/src/nxt_application.h b/src/nxt_application.h
index 972a712b..b4231e3b 100644
--- a/src/nxt_application.h
+++ b/src/nxt_application.h
@@ -27,6 +27,8 @@ typedef enum {
typedef struct nxt_app_module_s nxt_app_module_t;
+typedef nxt_int_t (*nxt_application_setup_t)(nxt_task_t *task,
+ nxt_process_t *process, nxt_common_app_conf_t *conf);
typedef struct {
@@ -37,9 +39,6 @@ typedef struct {
} nxt_app_lang_module_t;
-typedef struct nxt_common_app_conf_s nxt_common_app_conf_t;
-
-
typedef struct {
char *executable;
nxt_conf_value_t *arguments;
@@ -111,10 +110,8 @@ struct nxt_app_module_s {
nxt_str_t type;
const char *version;
- nxt_int_t (*pre_init)(nxt_task_t *task,
- nxt_common_app_conf_t *conf);
- nxt_int_t (*init)(nxt_task_t *task,
- nxt_common_app_conf_t *conf);
+ nxt_application_setup_t setup;
+ nxt_process_start_t start;
};
diff --git a/src/nxt_cert.c b/src/nxt_cert.c
index ee258646..9e825d80 100644
--- a/src/nxt_cert.c
+++ b/src/nxt_cert.c
@@ -797,12 +797,11 @@ nxt_cert_info_delete(nxt_str_t *name)
nxt_array_t *
-nxt_cert_store_load(nxt_task_t *task)
+nxt_cert_store_load(nxt_task_t *task, nxt_mp_t *mp)
{
DIR *dir;
size_t size, alloc;
u_char *buf, *p;
- nxt_mp_t *mp;
nxt_str_t name;
nxt_int_t ret;
nxt_file_t file;
@@ -818,14 +817,8 @@ nxt_cert_store_load(nxt_task_t *task)
return NULL;
}
- mp = nxt_mp_create(1024, 128, 256, 32);
- if (nxt_slow_path(mp == NULL)) {
- return NULL;
- }
-
certs = nxt_array_create(mp, 16, sizeof(nxt_cert_item_t));
if (nxt_slow_path(certs == NULL)) {
- nxt_mp_destroy(mp);
return NULL;
}
@@ -933,7 +926,7 @@ nxt_cert_store_release(nxt_array_t *certs)
nxt_fd_close(items[i].fd);
}
- nxt_mp_destroy(certs->mem_pool);
+ nxt_array_destroy(certs);
}
diff --git a/src/nxt_cert.h b/src/nxt_cert.h
index 319d5d3c..dbaddcf9 100644
--- a/src/nxt_cert.h
+++ b/src/nxt_cert.h
@@ -19,7 +19,7 @@ nxt_conf_value_t *nxt_cert_info_get(nxt_str_t *name);
nxt_conf_value_t *nxt_cert_info_get_all(nxt_mp_t *mp);
nxt_int_t nxt_cert_info_delete(nxt_str_t *name);
-nxt_array_t *nxt_cert_store_load(nxt_task_t *task);
+nxt_array_t *nxt_cert_store_load(nxt_task_t *task, nxt_mp_t *mem_pool);
void nxt_cert_store_release(nxt_array_t *certs);
void nxt_cert_store_get(nxt_task_t *task, nxt_str_t *name, nxt_mp_t *mp,
diff --git a/src/nxt_clone.h b/src/nxt_clone.h
index dcccf1db..c2066ce6 100644
--- a/src/nxt_clone.h
+++ b/src/nxt_clone.h
@@ -3,8 +3,8 @@
* Copyright (C) NGINX, Inc.
*/
-#ifndef _NXT_CLONE_INCLUDED_
-#define _NXT_CLONE_INCLUDED_
+#ifndef _NXT_CLONE_H_INCLUDED_
+#define _NXT_CLONE_H_INCLUDED_
#if (NXT_HAVE_CLONE_NEWUSER)
@@ -36,10 +36,11 @@ typedef struct {
pid_t nxt_clone(nxt_int_t flags);
-#if (NXT_HAVE_CLONE_NEWUSER)
+#define nxt_is_clone_flag_set(flags, test) \
+ ((flags & CLONE_##test) == CLONE_##test)
+
-#define NXT_CLONE_USER(flags) \
- ((flags & CLONE_NEWUSER) == CLONE_NEWUSER)
+#if (NXT_HAVE_CLONE_NEWUSER)
NXT_EXPORT nxt_int_t nxt_clone_credential_map(nxt_task_t *task, pid_t pid,
nxt_credential_t *creds, nxt_clone_t *clone);
@@ -50,4 +51,5 @@ NXT_EXPORT nxt_int_t nxt_clone_vldt_credential_gidmap(nxt_task_t *task,
#endif
-#endif /* _NXT_CLONE_INCLUDED_ */
+
+#endif /* _NXT_CLONE_H_INCLUDED_ */
diff --git a/src/nxt_controller.c b/src/nxt_controller.c
index ea70cf78..a61c127d 100644
--- a/src/nxt_controller.c
+++ b/src/nxt_controller.c
@@ -39,11 +39,17 @@ typedef struct {
} nxt_controller_response_t;
+static nxt_int_t nxt_controller_prefork(nxt_task_t *task,
+ nxt_process_t *process, nxt_mp_t *mp);
+static nxt_int_t nxt_controller_start(nxt_task_t *task,
+ nxt_process_data_t *data);
static void nxt_controller_process_new_port_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
static void nxt_controller_send_current_conf(nxt_task_t *task);
static void nxt_controller_router_ready_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
+static void nxt_controller_remove_pid_handler(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg);
static nxt_int_t nxt_controller_conf_default(void);
static void nxt_controller_conf_init_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg, void *data);
@@ -83,6 +89,8 @@ static void nxt_controller_process_cert(nxt_task_t *task,
static void nxt_controller_process_cert_save(nxt_task_t *task,
nxt_port_recv_msg_t *msg, void *data);
static nxt_bool_t nxt_controller_cert_in_use(nxt_str_t *name);
+static void nxt_controller_cert_cleanup(nxt_task_t *task, void *obj,
+ void *data);
#endif
static void nxt_controller_conf_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg, void *data);
@@ -114,21 +122,117 @@ static const nxt_event_conn_state_t nxt_controller_conn_write_state;
static const nxt_event_conn_state_t nxt_controller_conn_close_state;
-nxt_port_handlers_t nxt_controller_process_port_handlers = {
- .quit = nxt_worker_process_quit_handler,
+static const nxt_port_handlers_t nxt_controller_process_port_handlers = {
+ .quit = nxt_signal_quit_handler,
.new_port = nxt_controller_process_new_port_handler,
.change_file = nxt_port_change_log_file_handler,
.mmap = nxt_port_mmap_handler,
.process_ready = nxt_controller_router_ready_handler,
.data = nxt_port_data_handler,
- .remove_pid = nxt_port_remove_pid_handler,
+ .remove_pid = nxt_controller_remove_pid_handler,
.rpc_ready = nxt_port_rpc_handler,
.rpc_error = nxt_port_rpc_handler,
};
-nxt_int_t
-nxt_controller_start(nxt_task_t *task, void *data)
+const nxt_process_init_t nxt_controller_process = {
+ .name = "controller",
+ .type = NXT_PROCESS_CONTROLLER,
+ .prefork = nxt_controller_prefork,
+ .restart = 1,
+ .setup = nxt_process_core_setup,
+ .start = nxt_controller_start,
+ .port_handlers = &nxt_controller_process_port_handlers,
+ .signals = nxt_process_signals,
+};
+
+
+static nxt_int_t
+nxt_controller_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
+{
+ ssize_t n;
+ nxt_int_t ret;
+ nxt_str_t *conf;
+ nxt_file_t file;
+ nxt_runtime_t *rt;
+ nxt_file_info_t fi;
+ nxt_controller_init_t ctrl_init;
+
+ nxt_log(task, NXT_LOG_INFO, "controller started");
+
+ rt = task->thread->runtime;
+
+ nxt_memzero(&ctrl_init, sizeof(nxt_controller_init_t));
+
+ conf = &ctrl_init.conf;
+
+ nxt_memzero(&file, sizeof(nxt_file_t));
+
+ file.name = (nxt_file_name_t *) rt->conf;
+
+ ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0);
+
+ if (ret == NXT_OK) {
+ ret = nxt_file_info(&file, &fi);
+
+ if (nxt_fast_path(ret == NXT_OK && nxt_is_file(&fi))) {
+ conf->length = nxt_file_size(&fi);
+ conf->start = nxt_mp_alloc(mp, conf->length);
+ if (nxt_slow_path(conf->start == NULL)) {
+ nxt_file_close(task, &file);
+ return NXT_ERROR;
+ }
+
+ n = nxt_file_read(&file, conf->start, conf->length, 0);
+
+ if (nxt_slow_path(n != (ssize_t) conf->length)) {
+ conf->start = NULL;
+ conf->length = 0;
+
+ nxt_alert(task, "failed to restore previous configuration: "
+ "cannot read the file");
+ }
+ }
+
+ nxt_file_close(task, &file);
+ }
+
+#if (NXT_TLS)
+ ctrl_init.certs = nxt_cert_store_load(task, mp);
+
+ nxt_mp_cleanup(mp, nxt_controller_cert_cleanup, task, ctrl_init.certs, rt);
+#endif
+
+ process->data.controller = ctrl_init;
+
+ return NXT_OK;
+}
+
+
+#if (NXT_TLS)
+
+static void
+nxt_controller_cert_cleanup(nxt_task_t *task, void *obj, void *data)
+{
+ pid_t main_pid;
+ nxt_array_t *certs;
+ nxt_runtime_t *rt;
+
+ certs = obj;
+ rt = data;
+
+ main_pid = rt->port_by_type[NXT_PROCESS_MAIN]->pid;
+
+ if (nxt_pid == main_pid && certs != NULL) {
+ nxt_cert_store_release(certs);
+ }
+}
+
+#endif
+
+
+static nxt_int_t
+nxt_controller_start(nxt_task_t *task, nxt_process_data_t *data)
{
nxt_mp_t *mp;
nxt_int_t ret;
@@ -147,15 +251,13 @@ nxt_controller_start(nxt_task_t *task, void *data)
nxt_queue_init(&nxt_controller_waiting_requests);
- init = data;
+ init = &data->controller;
#if (NXT_TLS)
-
if (init->certs != NULL) {
nxt_cert_info_init(task, init->certs);
nxt_cert_store_release(init->certs);
}
-
#endif
json = &init->conf;
@@ -170,8 +272,6 @@ nxt_controller_start(nxt_task_t *task, void *data)
}
conf = nxt_conf_json_parse_str(mp, json);
- nxt_free(json->start);
-
if (nxt_slow_path(conf == NULL)) {
nxt_alert(task, "failed to restore previous configuration: "
"file is corrupted or not enough memory");
@@ -295,6 +395,28 @@ nxt_controller_router_ready_handler(nxt_task_t *task,
}
+static void
+nxt_controller_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
+{
+ nxt_pid_t pid;
+ nxt_process_t *process;
+ nxt_runtime_t *rt;
+
+ rt = task->thread->runtime;
+
+ nxt_assert(nxt_buf_used_size(msg->buf) == sizeof(pid));
+
+ nxt_memcpy(&pid, msg->buf->mem.pos, sizeof(pid));
+
+ process = nxt_runtime_process_find(rt, pid);
+ if (process != NULL && nxt_process_type(process) == NXT_PROCESS_ROUTER) {
+ nxt_controller_router_ready = 0;
+ }
+
+ nxt_port_remove_pid_handler(task, msg);
+}
+
+
static nxt_int_t
nxt_controller_conf_default(void)
{
diff --git a/src/nxt_external.c b/src/nxt_external.c
index e498a938..58523525 100644
--- a/src/nxt_external.c
+++ b/src/nxt_external.c
@@ -9,8 +9,7 @@
#include <nxt_unit.h>
-static nxt_int_t nxt_external_init(nxt_task_t *task,
- nxt_common_app_conf_t *conf);
+static nxt_int_t nxt_external_start(nxt_task_t *task, nxt_process_data_t *data);
nxt_app_module_t nxt_external_module = {
@@ -19,7 +18,7 @@ nxt_app_module_t nxt_external_module = {
nxt_string("external"),
"*",
NULL,
- nxt_external_init,
+ nxt_external_start,
};
@@ -58,7 +57,7 @@ nxt_external_fd_no_cloexec(nxt_task_t *task, nxt_socket_t fd)
static nxt_int_t
-nxt_external_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
+nxt_external_start(nxt_task_t *task, nxt_process_data_t *data)
{
char **argv;
u_char buf[256];
@@ -71,9 +70,11 @@ nxt_external_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
nxt_port_t *my_port, *main_port;
nxt_runtime_t *rt;
nxt_conf_value_t *value;
+ nxt_common_app_conf_t *conf;
nxt_external_app_conf_t *c;
rt = task->thread->runtime;
+ conf = data->app;
main_port = rt->port_by_type[NXT_PROCESS_MAIN];
my_port = nxt_runtime_port_find(rt, nxt_pid, 0);
@@ -99,7 +100,7 @@ nxt_external_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
"%PI,%ud,%d;"
"%PI,%ud,%d;"
"%d,%z,%Z",
- NXT_VERSION, my_port->process->init->stream,
+ NXT_VERSION, my_port->process->stream,
main_port->pid, main_port->id, main_port->pair[1],
my_port->pid, my_port->id, my_port->pair[0],
2, conf->shm_limit);
diff --git a/src/nxt_java.c b/src/nxt_java.c
index 004907d6..c4145c1d 100644
--- a/src/nxt_java.c
+++ b/src/nxt_java.c
@@ -27,9 +27,10 @@
#include "nxt_jars.h"
-static nxt_int_t nxt_java_pre_init(nxt_task_t *task,
+static nxt_int_t nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
nxt_common_app_conf_t *conf);
-static nxt_int_t nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
+static nxt_int_t nxt_java_start(nxt_task_t *task,
+ nxt_process_data_t *data);
static void nxt_java_request_handler(nxt_unit_request_info_t *req);
static void nxt_java_websocket_handler(nxt_unit_websocket_frame_t *ws);
static void nxt_java_close_handler(nxt_unit_request_info_t *req);
@@ -49,8 +50,8 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
compat,
nxt_string("java"),
NXT_STRING(NXT_JAVA_VERSION),
- nxt_java_pre_init,
- nxt_java_init,
+ nxt_java_setup,
+ nxt_java_start,
};
typedef struct {
@@ -60,7 +61,8 @@ typedef struct {
static nxt_int_t
-nxt_java_pre_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
+nxt_java_setup(nxt_task_t *task, nxt_process_t *process,
+ nxt_common_app_conf_t *conf)
{
const char *unit_jars;
@@ -115,24 +117,26 @@ nxt_java_module_jars(const char *jars[], int jar_count)
static nxt_int_t
-nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
+nxt_java_start(nxt_task_t *task, nxt_process_data_t *data)
{
- jint rc;
- char *opt, *real_path;
- char **classpath_arr, **unit_jars, **system_jars;
- JavaVM *jvm;
- JNIEnv *env;
- jobject cl, classpath;
- nxt_str_t str;
- nxt_int_t opt_len, real_path_len;
- nxt_uint_t i, unit_jars_count, classpath_count, system_jars_count;
- JavaVMOption *jvm_opt;
- JavaVMInitArgs jvm_args;
- nxt_unit_ctx_t *ctx;
- nxt_unit_init_t java_init;
- nxt_java_data_t data;
- nxt_conf_value_t *value;
- nxt_java_app_conf_t *c;
+ jint rc;
+ char *opt, *real_path;
+ char **classpath_arr, **unit_jars, **system_jars;
+ JavaVM *jvm;
+ JNIEnv *env;
+ jobject cl, classpath;
+ nxt_str_t str;
+ nxt_int_t opt_len, real_path_len;
+ nxt_uint_t i, unit_jars_count, classpath_count;
+ nxt_uint_t system_jars_count;
+ JavaVMOption *jvm_opt;
+ JavaVMInitArgs jvm_args;
+ nxt_unit_ctx_t *ctx;
+ nxt_unit_init_t java_init;
+ nxt_java_data_t java_data;
+ nxt_conf_value_t *value;
+ nxt_java_app_conf_t *c;
+ nxt_common_app_conf_t *app_conf;
//setenv("ASAN_OPTIONS", "handle_segv=0", 1);
@@ -140,7 +144,8 @@ nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
jvm_args.nOptions = 0;
jvm_args.ignoreUnrecognized = 0;
- c = &conf->u.java;
+ app_conf = data->app;
+ c = &app_conf->u.java;
if (c->options != NULL) {
jvm_args.nOptions += nxt_conf_array_elements_count(c->options);
@@ -338,8 +343,8 @@ nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
goto env_failed;
}
- data.env = env;
- data.ctx = nxt_java_startContext(env, c->webapp, classpath);
+ java_data.env = env;
+ java_data.ctx = nxt_java_startContext(env, c->webapp, classpath);
if ((*env)->ExceptionCheck(env)) {
nxt_alert(task, "Unhandled exception in application start");
@@ -353,8 +358,8 @@ nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
java_init.callbacks.websocket_handler = nxt_java_websocket_handler;
java_init.callbacks.close_handler = nxt_java_close_handler;
java_init.request_data_size = sizeof(nxt_java_request_data_t);
- java_init.data = &data;
- java_init.shm_limit = conf->shm_limit;
+ java_init.data = &java_data;
+ java_init.shm_limit = app_conf->shm_limit;
ctx = nxt_unit_init(&java_init);
if (nxt_slow_path(ctx == NULL)) {
@@ -367,7 +372,7 @@ nxt_java_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
/* TODO report error */
}
- nxt_java_stopContext(env, data.ctx);
+ nxt_java_stopContext(env, java_data.ctx);
if ((*env)->ExceptionCheck(env)) {
(*env)->ExceptionDescribe(env);
diff --git a/src/nxt_main_process.c b/src/nxt_main_process.c
index c35954c0..0dff050b 100644
--- a/src/nxt_main_process.c
+++ b/src/nxt_main_process.c
@@ -36,20 +36,11 @@ extern nxt_port_handlers_t nxt_router_process_port_handlers;
static nxt_int_t nxt_main_process_port_create(nxt_task_t *task,
nxt_runtime_t *rt);
static void nxt_main_process_title(nxt_task_t *task);
-static nxt_int_t nxt_main_start_controller_process(nxt_task_t *task,
- nxt_runtime_t *rt);
-static nxt_int_t nxt_main_create_controller_process(nxt_task_t *task,
- nxt_runtime_t *rt, nxt_process_init_t *init);
-static nxt_int_t nxt_main_create_router_process(nxt_task_t *task, nxt_runtime_t *rt,
- nxt_process_init_t *init);
-static nxt_int_t nxt_main_start_router_process(nxt_task_t *task,
- nxt_runtime_t *rt);
-static nxt_int_t nxt_main_start_discovery_process(nxt_task_t *task,
- nxt_runtime_t *rt);
-static nxt_int_t nxt_main_start_worker_process(nxt_task_t *task,
- nxt_runtime_t *rt, nxt_common_app_conf_t *app_conf, uint32_t stream);
-static nxt_int_t nxt_main_create_worker_process(nxt_task_t *task,
- nxt_runtime_t *rt, nxt_process_init_t *init);
+static nxt_int_t nxt_main_process_create(nxt_task_t *task,
+ const nxt_process_init_t init);
+static nxt_int_t nxt_main_start_process(nxt_task_t *task,
+ nxt_process_t *process);
+static nxt_process_t *nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt);
static void nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj,
void *data);
static void nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj,
@@ -60,8 +51,7 @@ static void nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj,
void *data);
static void nxt_main_process_signal_handler(nxt_task_t *task, void *obj,
void *data);
-static void nxt_main_cleanup_worker_process(nxt_task_t *task, nxt_pid_t pid);
-static void nxt_main_stop_worker_processes(nxt_task_t *task, nxt_runtime_t *rt);
+static void nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid);
static void nxt_main_port_socket_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
static nxt_int_t nxt_main_listening_socket(nxt_sockaddr_t *sa,
@@ -73,29 +63,6 @@ static void nxt_main_port_conf_store_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
static void nxt_main_port_access_log_handler(nxt_task_t *task,
nxt_port_recv_msg_t *msg);
-static nxt_process_init_t *nxt_process_init_create(nxt_task_t *task,
- nxt_process_type_t type, const nxt_str_t *name);
-static nxt_int_t nxt_process_init_name_set(nxt_process_init_t *init,
- nxt_process_type_t type, const nxt_str_t *name);
-static nxt_int_t nxt_process_init_creds_set(nxt_task_t *task,
- nxt_process_init_t *init, nxt_str_t *user, nxt_str_t *group);
-
-static nxt_int_t nxt_init_isolation(nxt_task_t *task,
- nxt_conf_value_t *isolation, nxt_process_init_t *init);
-#if (NXT_HAVE_CLONE)
-static nxt_int_t nxt_init_clone_flags(nxt_task_t *task,
- nxt_conf_value_t *namespaces, nxt_process_init_t *init);
-#endif
-
-#if (NXT_HAVE_CLONE_NEWUSER)
-static nxt_int_t nxt_init_isolation_creds(nxt_task_t *task,
- nxt_conf_value_t *isolation, nxt_process_init_t *init);
-static nxt_int_t nxt_init_vldt_isolation_creds(nxt_task_t *task,
- nxt_process_init_t *init);
-static nxt_int_t nxt_init_isolation_credential_map(nxt_task_t *task,
- nxt_mp_t *mem_pool, nxt_conf_value_t *map_array,
- nxt_clone_credential_map_t *map);
-#endif
const nxt_sig_event_t nxt_main_process_signals[] = {
nxt_event_signal(SIGHUP, nxt_main_process_signal_handler),
@@ -108,54 +75,6 @@ const nxt_sig_event_t nxt_main_process_signals[] = {
};
-static const nxt_port_handlers_t nxt_app_process_port_handlers = {
- .new_port = nxt_port_new_port_handler,
- .change_file = nxt_port_change_log_file_handler,
- .mmap = nxt_port_mmap_handler,
- .remove_pid = nxt_port_remove_pid_handler,
-};
-
-
-static const nxt_port_handlers_t nxt_discovery_process_port_handlers = {
- .quit = nxt_worker_process_quit_handler,
- .new_port = nxt_port_new_port_handler,
- .change_file = nxt_port_change_log_file_handler,
- .mmap = nxt_port_mmap_handler,
- .data = nxt_port_data_handler,
- .remove_pid = nxt_port_remove_pid_handler,
- .rpc_ready = nxt_port_rpc_handler,
- .rpc_error = nxt_port_rpc_handler,
-};
-
-
-static const nxt_port_handlers_t *nxt_process_port_handlers[NXT_PROCESS_MAX] =
-{
- NULL,
- &nxt_discovery_process_port_handlers,
- &nxt_controller_process_port_handlers,
- &nxt_router_process_port_handlers,
- &nxt_app_process_port_handlers
-};
-
-
-static const nxt_process_start_t nxt_process_starts[NXT_PROCESS_MAX] = {
- NULL,
- nxt_discovery_start,
- nxt_controller_start,
- nxt_router_start,
- nxt_app_start
-};
-
-
-static const nxt_process_restart_t nxt_process_restarts[NXT_PROCESS_MAX] = {
- NULL,
- NULL,
- &nxt_main_create_controller_process,
- &nxt_main_create_router_process,
- NULL
-};
-
-
static nxt_bool_t nxt_exiting;
@@ -172,11 +91,11 @@ nxt_main_process_start(nxt_thread_t *thr, nxt_task_t *task,
nxt_main_process_title(task);
/*
- * The dicsovery process will send a message processed by
+ * The discovery process will send a message processed by
* nxt_main_port_modules_handler() which starts the controller
* and router processes.
*/
- return nxt_main_start_discovery_process(task, rt);
+ return nxt_main_process_create(task, nxt_discovery_process);
}
@@ -350,48 +269,71 @@ nxt_port_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
static void
-nxt_port_main_start_worker_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
+nxt_port_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
{
- u_char *start, ch;
+ u_char *start, *p, ch;
size_t type_len;
- nxt_mp_t *mp;
nxt_int_t ret;
nxt_buf_t *b;
nxt_port_t *port;
nxt_runtime_t *rt;
+ nxt_process_t *process;
nxt_app_type_t idx;
nxt_conf_value_t *conf;
- nxt_common_app_conf_t app_conf;
+ nxt_process_init_t *init;
+ nxt_common_app_conf_t *app_conf;
ret = NXT_ERROR;
- mp = nxt_mp_create(1024, 128, 256, 32);
+ rt = task->thread->runtime;
- if (nxt_slow_path(mp == NULL)) {
+ process = nxt_main_process_new(task, rt);
+ if (nxt_slow_path(process == NULL)) {
return;
}
- b = nxt_buf_chk_make_plain(mp, msg->buf, msg->size);
+ init = nxt_process_init(process);
+
+ *init = nxt_app_process;
+ b = nxt_buf_chk_make_plain(process->mem_pool, msg->buf, msg->size);
if (b == NULL) {
- return;
+ goto failed;
}
- nxt_debug(task, "main start worker: %*s", b->mem.free - b->mem.pos,
+ nxt_debug(task, "main start process: %*s", b->mem.free - b->mem.pos,
b->mem.pos);
- nxt_memzero(&app_conf, sizeof(nxt_common_app_conf_t));
+ app_conf = nxt_mp_zalloc(process->mem_pool, sizeof(nxt_common_app_conf_t));
+ if (nxt_slow_path(app_conf == NULL)) {
+ goto failed;
+ }
start = b->mem.pos;
- app_conf.name.start = start;
- app_conf.name.length = nxt_strlen(start);
- app_conf.shm_limit = 100 * 1024 * 1024;
+ app_conf->name.start = start;
+ app_conf->name.length = nxt_strlen(start);
+
+ init->name = (const char *) start;
- start += app_conf.name.length + 1;
+ process->name = nxt_mp_alloc(process->mem_pool, app_conf->name.length
+ + sizeof("\"\" application") + 1);
- conf = nxt_conf_json_parse(mp, start, b->mem.free, NULL);
+ if (nxt_slow_path(process->name == NULL)) {
+ goto failed;
+ }
+
+ p = (u_char *) process->name;
+ *p++ = '"';
+ p = nxt_cpymem(p, init->name, app_conf->name.length);
+ p = nxt_cpymem(p, "\" application", 13);
+ *p = '\0';
+ app_conf->shm_limit = 100 * 1024 * 1024;
+
+ start += app_conf->name.length + 1;
+
+ conf = nxt_conf_json_parse(process->mem_pool, start, b->mem.free, NULL);
if (conf == NULL) {
nxt_alert(task, "router app configuration parsing error");
@@ -400,44 +342,45 @@ nxt_port_main_start_worker_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
rt = task->thread->runtime;
- app_conf.user.start = (u_char*)rt->user_cred.user;
- app_conf.user.length = nxt_strlen(rt->user_cred.user);
+ app_conf->user.start = (u_char*)rt->user_cred.user;
+ app_conf->user.length = nxt_strlen(rt->user_cred.user);
+
+ ret = nxt_conf_map_object(process->mem_pool, conf, nxt_common_app_conf,
+ nxt_nitems(nxt_common_app_conf), app_conf);
- ret = nxt_conf_map_object(mp, conf, nxt_common_app_conf,
- nxt_nitems(nxt_common_app_conf), &app_conf);
if (ret != NXT_OK) {
nxt_alert(task, "failed to map common app conf received from router");
goto failed;
}
- for (type_len = 0; type_len != app_conf.type.length; type_len++) {
- ch = app_conf.type.start[type_len];
+ for (type_len = 0; type_len != app_conf->type.length; type_len++) {
+ ch = app_conf->type.start[type_len];
if (ch == ' ' || nxt_isdigit(ch)) {
break;
}
}
- idx = nxt_app_parse_type(app_conf.type.start, type_len);
+ idx = nxt_app_parse_type(app_conf->type.start, type_len);
if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) {
nxt_alert(task, "invalid app type %d received from router", (int) idx);
goto failed;
}
- ret = nxt_conf_map_object(mp, conf, nxt_app_maps[idx].map,
- nxt_app_maps[idx].size, &app_conf);
+ ret = nxt_conf_map_object(process->mem_pool, conf, nxt_app_maps[idx].map,
+ nxt_app_maps[idx].size, app_conf);
if (nxt_slow_path(ret != NXT_OK)) {
nxt_alert(task, "failed to map app conf received from router");
goto failed;
}
- if (app_conf.limits != NULL) {
- ret = nxt_conf_map_object(mp, app_conf.limits,
+ if (app_conf->limits != NULL) {
+ ret = nxt_conf_map_object(process->mem_pool, app_conf->limits,
nxt_common_app_limits_conf,
nxt_nitems(nxt_common_app_limits_conf),
- &app_conf);
+ app_conf);
if (nxt_slow_path(ret != NXT_OK)) {
nxt_alert(task, "failed to map app limits received from router");
@@ -445,40 +388,91 @@ nxt_port_main_start_worker_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
}
}
- app_conf.self = conf;
+ app_conf->self = conf;
- ret = nxt_main_start_worker_process(task, task->thread->runtime,
- &app_conf, msg->port_msg.stream);
+ process->stream = msg->port_msg.stream;
+ process->data.app = app_conf;
+
+ ret = nxt_main_start_process(task, process);
+ if (nxt_fast_path(ret == NXT_OK || ret == NXT_AGAIN)) {
+ return;
+ }
failed:
- if (ret == NXT_ERROR) {
- port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
- msg->port_msg.reply_port);
- if (nxt_fast_path(port != NULL)) {
- nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
- -1, msg->port_msg.stream, 0, NULL);
- }
+ nxt_process_use(task, process, -1);
+
+ port = nxt_runtime_port_find(rt, msg->port_msg.pid,
+ msg->port_msg.reply_port);
+
+ if (nxt_fast_path(port != NULL)) {
+ nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
+ -1, msg->port_msg.stream, 0, NULL);
}
+}
- nxt_mp_destroy(mp);
+
+static void
+nxt_main_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
+{
+ nxt_port_t *port;
+ nxt_process_t *process;
+ nxt_runtime_t *rt;
+
+ rt = task->thread->runtime;
+
+ process = nxt_runtime_process_find(rt, msg->port_msg.pid);
+ if (nxt_slow_path(process == NULL)) {
+ return;
+ }
+
+ nxt_assert(process->state == NXT_PROCESS_STATE_CREATING);
+
+ port = nxt_runtime_port_find(rt, msg->port_msg.pid,
+ msg->port_msg.reply_port);
+
+
+ if (nxt_slow_path(port == NULL)) {
+ return;
+ }
+
+#if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER)
+ if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
+ if (nxt_slow_path(nxt_clone_credential_map(task, process->pid,
+ process->user_cred,
+ &process->isolation.clone)
+ != NXT_OK))
+ {
+ (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
+ -1, msg->port_msg.stream, 0, NULL);
+ return;
+ }
+ }
+
+#endif
+
+ process->state = NXT_PROCESS_STATE_CREATED;
+
+ (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST,
+ -1, msg->port_msg.stream, 0, NULL);
}
static nxt_port_handlers_t nxt_main_process_port_handlers = {
- .data = nxt_port_main_data_handler,
- .process_ready = nxt_port_process_ready_handler,
- .start_worker = nxt_port_main_start_worker_handler,
- .socket = nxt_main_port_socket_handler,
- .modules = nxt_main_port_modules_handler,
- .conf_store = nxt_main_port_conf_store_handler,
+ .data = nxt_port_main_data_handler,
+ .process_created = nxt_main_process_created_handler,
+ .process_ready = nxt_port_process_ready_handler,
+ .start_process = nxt_port_main_start_process_handler,
+ .socket = nxt_main_port_socket_handler,
+ .modules = nxt_main_port_modules_handler,
+ .conf_store = nxt_main_port_conf_store_handler,
#if (NXT_TLS)
- .cert_get = nxt_cert_store_get_handler,
- .cert_delete = nxt_cert_store_delete_handler,
+ .cert_get = nxt_cert_store_get_handler,
+ .cert_delete = nxt_cert_store_delete_handler,
#endif
- .access_log = nxt_main_port_access_log_handler,
- .rpc_ready = nxt_port_rpc_handler,
- .rpc_error = nxt_port_rpc_handler,
+ .access_log = nxt_main_port_access_log_handler,
+ .rpc_ready = nxt_port_rpc_handler,
+ .rpc_error = nxt_port_rpc_handler,
};
@@ -499,16 +493,17 @@ nxt_main_process_port_create(nxt_task_t *task, nxt_runtime_t *rt)
ret = nxt_port_socket_init(task, port, 0);
if (nxt_slow_path(ret != NXT_OK)) {
+ nxt_port_use(task, port, -1);
return ret;
}
/*
* A main process port. A write port is not closed
- * since it should be inherited by worker processes.
+ * since it should be inherited by processes.
*/
nxt_port_enable(task, port, &nxt_main_process_port_handlers);
- process->ready = 1;
+ process->state = NXT_PROCESS_STATE_READY;
return NXT_OK;
}
@@ -541,234 +536,68 @@ nxt_main_process_title(nxt_task_t *task)
static nxt_int_t
-nxt_main_start_controller_process(nxt_task_t *task, nxt_runtime_t *rt)
+nxt_main_process_create(nxt_task_t *task, const nxt_process_init_t init)
{
- nxt_process_init_t *init;
+ nxt_int_t ret;
+ nxt_runtime_t *rt;
+ nxt_process_t *process;
+ nxt_process_init_t *pinit;
- static const nxt_str_t name = nxt_string("controller");
+ rt = task->thread->runtime;
- init = nxt_process_init_create(task, NXT_PROCESS_CONTROLLER, &name);
- if (nxt_slow_path(init == NULL)) {
+ process = nxt_main_process_new(task, rt);
+ if (nxt_slow_path(process == NULL)) {
return NXT_ERROR;
}
- return nxt_main_create_controller_process(task, rt, init);;
-}
+ process->name = init.name;
+ process->user_cred = &rt->user_cred;
+ pinit = nxt_process_init(process);
+ *pinit = init;
-static nxt_int_t
-nxt_main_create_controller_process(nxt_task_t *task, nxt_runtime_t *rt,
- nxt_process_init_t *init)
-{
- ssize_t n;
- nxt_int_t ret;
- nxt_str_t *conf;
- nxt_file_t file;
- nxt_file_info_t fi;
- nxt_controller_init_t ctrl_init;
-
- nxt_memzero(&ctrl_init, sizeof(nxt_controller_init_t));
-
- conf = &ctrl_init.conf;
-
- nxt_memzero(&file, sizeof(nxt_file_t));
-
- file.name = (nxt_file_name_t *) rt->conf;
-
- ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0);
-
- if (ret == NXT_OK) {
- ret = nxt_file_info(&file, &fi);
-
- if (nxt_fast_path(ret == NXT_OK && nxt_is_file(&fi))) {
- conf->length = nxt_file_size(&fi);
- conf->start = nxt_malloc(conf->length);
-
- if (nxt_slow_path(conf->start == NULL)) {
- nxt_file_close(task, &file);
- return NXT_ERROR;
- }
-
- n = nxt_file_read(&file, conf->start, conf->length, 0);
-
- if (nxt_slow_path(n != (ssize_t) conf->length)) {
- nxt_free(conf->start);
- conf->start = NULL;
-
- nxt_alert(task, "failed to restore previous configuration: "
- "cannot read the file");
- }
- }
-
- nxt_file_close(task, &file);
- }
-
-#if (NXT_TLS)
- ctrl_init.certs = nxt_cert_store_load(task);
-#endif
-
- init->data = &ctrl_init;
-
- ret = nxt_main_create_worker_process(task, rt, init);
-
- if (ret == NXT_OK) {
- if (conf->start != NULL) {
- nxt_free(conf->start);
- }
-
-#if (NXT_TLS)
- if (ctrl_init.certs != NULL) {
- nxt_cert_store_release(ctrl_init.certs);
- }
-#endif
+ ret = nxt_main_start_process(task, process);
+ if (nxt_slow_path(ret == NXT_ERROR)) {
+ nxt_process_use(task, process, -1);
}
return ret;
}
-static nxt_int_t
-nxt_main_start_discovery_process(nxt_task_t *task, nxt_runtime_t *rt)
+static nxt_process_t *
+nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt)
{
- nxt_process_init_t *init;
-
- static const nxt_str_t name = nxt_string("discovery");
+ nxt_process_t *process;
- init = nxt_process_init_create(task, NXT_PROCESS_DISCOVERY, &name);
- if (nxt_slow_path(init == NULL)) {
- return NXT_ERROR;
+ process = nxt_runtime_process_new(rt);
+ if (nxt_slow_path(process == NULL)) {
+ return NULL;
}
- return nxt_main_create_worker_process(task, rt, init);
-}
-
-
-static nxt_int_t
-nxt_main_start_router_process(nxt_task_t *task, nxt_runtime_t *rt)
-{
- nxt_process_init_t *init;
-
- static const nxt_str_t name = nxt_string("router");
-
- init = nxt_process_init_create(task, NXT_PROCESS_ROUTER, &name);
- if (nxt_slow_path(init == NULL)) {
- return NXT_ERROR;
+ process->mem_pool = nxt_mp_create(1024, 128, 256, 32);
+ if (process->mem_pool == NULL) {
+ nxt_process_use(task, process, -1);
+ return NULL;
}
- return nxt_main_create_router_process(task, rt, init);
+ return process;
}
static nxt_int_t
-nxt_main_create_router_process(nxt_task_t *task, nxt_runtime_t *rt,
- nxt_process_init_t *init)
+nxt_main_start_process(nxt_task_t *task, nxt_process_t *process)
{
- nxt_main_stop_worker_processes(task, rt);
-
- return nxt_main_create_worker_process(task, rt, init);
-}
-
-
-static nxt_int_t
-nxt_main_start_worker_process(nxt_task_t *task, nxt_runtime_t *rt,
- nxt_common_app_conf_t *app_conf, uint32_t stream)
-{
- nxt_int_t cap_setid;
+ nxt_mp_t *tmp_mp;
nxt_int_t ret;
+ nxt_pid_t pid;
+ nxt_port_t *port;
nxt_process_init_t *init;
- init = nxt_process_init_create(task, NXT_PROCESS_WORKER, &app_conf->name);
- if (nxt_slow_path(init == NULL)) {
- return NXT_ERROR;
- }
-
- cap_setid = rt->capabilities.setid;
-
- if (app_conf->isolation != NULL) {
- ret = nxt_init_isolation(task, app_conf->isolation, init);
- if (nxt_slow_path(ret != NXT_OK)) {
- goto fail;
- }
- }
-
-#if (NXT_HAVE_CLONE_NEWUSER)
- if (NXT_CLONE_USER(init->isolation.clone.flags)) {
- cap_setid = 1;
- }
-#endif
-
- if (cap_setid) {
- ret = nxt_process_init_creds_set(task, init, &app_conf->user,
- &app_conf->group);
- if (nxt_slow_path(ret != NXT_OK)) {
- goto fail;
- }
-
- } else {
- if (!nxt_str_eq(&app_conf->user, (u_char *) rt->user_cred.user,
- nxt_strlen(rt->user_cred.user)))
- {
- nxt_alert(task, "cannot set user \"%V\" for app \"%V\": "
- "missing capabilities", &app_conf->user, &app_conf->name);
- goto fail;
- }
-
- if (app_conf->group.length > 0
- && !nxt_str_eq(&app_conf->group, (u_char *) rt->group,
- nxt_strlen(rt->group)))
- {
- nxt_alert(task, "cannot set group \"%V\" for app \"%V\": "
- "missing capabilities", &app_conf->group,
- &app_conf->name);
- goto fail;
- }
- }
-
- init->data = app_conf;
- init->stream = stream;
-
-#if (NXT_HAVE_CLONE_NEWUSER)
- ret = nxt_init_vldt_isolation_creds(task, init);
- if (nxt_slow_path(ret != NXT_OK)) {
- goto fail;
- }
-#endif
-
- return nxt_main_create_worker_process(task, rt, init);
-
-fail:
-
- nxt_mp_destroy(init->mem_pool);
-
- return NXT_ERROR;
-}
-
-
-nxt_int_t
-nxt_main_create_worker_process(nxt_task_t *task, nxt_runtime_t *rt,
- nxt_process_init_t *init)
-{
- nxt_int_t ret;
- nxt_pid_t pid;
- nxt_port_t *port;
- nxt_process_t *process;
-
- /*
- * TODO: remove process, init, ports from array on memory and fork failures.
- */
-
- process = nxt_runtime_process_new(rt);
- if (nxt_slow_path(process == NULL)) {
- nxt_mp_destroy(init->mem_pool);
-
- return NXT_ERROR;
- }
-
- process->init = init;
+ init = nxt_process_init(process);
port = nxt_port_new(task, 0, 0, init->type);
if (nxt_slow_path(port == NULL)) {
- nxt_process_use(task, process, -1);
return NXT_ERROR;
}
@@ -776,10 +605,24 @@ nxt_main_create_worker_process(nxt_task_t *task, nxt_runtime_t *rt,
nxt_process_use(task, process, -1);
+ ret = NXT_ERROR;
+ tmp_mp = NULL;
+
ret = nxt_port_socket_init(task, port, 0);
if (nxt_slow_path(ret != NXT_OK)) {
- nxt_port_use(task, port, -1);
- return ret;
+ goto fail;
+ }
+
+ tmp_mp = nxt_mp_create(1024, 128, 256, 32);
+ if (tmp_mp == NULL) {
+ goto fail;
+ }
+
+ if (init->prefork) {
+ ret = init->prefork(task, process, tmp_mp);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ goto fail;
+ }
}
pid = nxt_process_create(task, process);
@@ -788,15 +631,13 @@ nxt_main_create_worker_process(nxt_task_t *task, nxt_runtime_t *rt,
case -1:
nxt_port_close(task, port);
- nxt_port_use(task, port, -1);
-
- return NXT_ERROR;
+ break;
case 0:
- /* A worker process, return to the event engine work queue loop. */
- nxt_port_use(task, port, -1);
+ /* The child process: return to the event engine work queue loop. */
- return NXT_AGAIN;
+ ret = NXT_AGAIN;
+ break;
default:
/* The main process created a new process. */
@@ -804,35 +645,22 @@ nxt_main_create_worker_process(nxt_task_t *task, nxt_runtime_t *rt,
nxt_port_read_close(port);
nxt_port_write_enable(task, port);
- nxt_port_use(task, port, -1);
-
- return NXT_OK;
+ ret = NXT_OK;
+ break;
}
-}
-
-void
-nxt_main_stop_all_processes(nxt_task_t *task, nxt_runtime_t *rt)
-{
- nxt_port_t *port;
- nxt_process_t *process;
-
- nxt_runtime_process_each(rt, process) {
-
- if (nxt_pid != process->pid) {
- nxt_process_port_each(process, port) {
+fail:
- (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT,
- -1, 0, 0, NULL);
+ nxt_port_use(task, port, -1);
- } nxt_process_port_loop;
- }
+ if (nxt_fast_path(tmp_mp != NULL)) {
+ nxt_mp_destroy(tmp_mp);
+ }
- } nxt_runtime_process_loop;
+ return ret;
}
-
static void
nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, void *data)
{
@@ -1009,7 +837,7 @@ nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, void *data)
pid, WEXITSTATUS(status));
}
- nxt_main_cleanup_worker_process(task, pid);
+ nxt_main_cleanup_process(task, pid);
}
}
@@ -1023,102 +851,81 @@ nxt_main_process_signal_handler(nxt_task_t *task, void *obj, void *data)
static void
-nxt_main_cleanup_worker_process(nxt_task_t *task, nxt_pid_t pid)
+nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid)
{
- nxt_buf_t *buf;
- nxt_port_t *port;
- nxt_runtime_t *rt;
- nxt_process_t *process;
- nxt_process_type_t ptype;
- nxt_process_init_t *init;
- nxt_process_restart_t restart;
+ int stream;
+ nxt_int_t ret;
+ nxt_buf_t *buf;
+ nxt_port_t *port;
+ const char *name;
+ nxt_runtime_t *rt;
+ nxt_process_t *process;
+ nxt_process_init_t init;
rt = task->thread->runtime;
process = nxt_runtime_process_find(rt, pid);
+ if (!process) {
+ return;
+ }
- if (process) {
- init = process->init;
- process->init = NULL;
+ name = process->name;
+ stream = process->stream;
+ init = *((nxt_process_init_t *) nxt_process_init(process));
- ptype = nxt_process_type(process);
- restart = nxt_process_restarts[ptype];
+ if (process->state == NXT_PROCESS_STATE_READY) {
+ process->stream = 0;
+ }
- if (process->ready) {
- init->stream = 0;
- }
+ nxt_process_close_ports(task, process);
- nxt_process_close_ports(task, process);
+ if (nxt_exiting) {
+ if (rt->nprocesses <= 1) {
+ nxt_runtime_quit(task, 0);
+ }
- if (nxt_exiting) {
- nxt_mp_destroy(init->mem_pool);
+ return;
+ }
- if (rt->nprocesses <= 2) {
- nxt_runtime_quit(task, 0);
- }
+ nxt_runtime_process_each(rt, process) {
- return;
+ if (process->pid == nxt_pid
+ || process->pid == pid
+ || nxt_queue_is_empty(&process->ports))
+ {
+ continue;
}
- nxt_runtime_process_each(rt, process) {
+ port = nxt_process_port_first(process);
- if (process->pid == nxt_pid
- || process->pid == pid
- || nxt_queue_is_empty(&process->ports))
- {
- continue;
- }
-
- port = nxt_process_port_first(process);
+ if (nxt_proc_remove_notify_matrix[init.type][port->type] == 0) {
+ continue;
+ }
- if (nxt_proc_remove_notify_matrix[ptype][port->type] == 0) {
- continue;
- }
+ buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
+ sizeof(pid));
- buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
- sizeof(pid));
- if (nxt_slow_path(buf == NULL)) {
- continue;
- }
+ if (nxt_slow_path(buf == NULL)) {
+ continue;
+ }
- buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid));
+ buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid));
- nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID,
- -1, init->stream, 0, buf);
- } nxt_runtime_process_loop;
+ nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID, -1,
+ stream, 0, buf);
- if (restart != NULL) {
- restart(task, rt, init);
+ } nxt_runtime_process_loop;
- } else {
- nxt_mp_destroy(init->mem_pool);
+ if (init.restart) {
+ ret = nxt_main_process_create(task, init);
+ if (nxt_slow_path(ret == NXT_ERROR)) {
+ nxt_alert(task, "failed to restart %s", name);
}
}
}
static void
-nxt_main_stop_worker_processes(nxt_task_t *task, nxt_runtime_t *rt)
-{
- nxt_port_t *port;
- nxt_process_t *process;
-
- nxt_runtime_process_each(rt, process) {
-
- nxt_process_port_each(process, port) {
-
- if (port->type == NXT_PROCESS_WORKER) {
- (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT,
- -1, 0, 0, NULL);
- }
-
- } nxt_process_port_loop;
-
- } nxt_runtime_process_loop;
-}
-
-
-static void
nxt_main_port_socket_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
{
size_t size;
@@ -1419,10 +1226,15 @@ fail:
nxt_mp_destroy(mp);
- ret = nxt_main_start_controller_process(task, rt);
-
+ ret = nxt_main_process_create(task, nxt_controller_process);
if (ret == NXT_OK) {
- (void) nxt_main_start_router_process(task, rt);
+ ret = nxt_main_process_create(task, nxt_router_process);
+ }
+
+ if (nxt_slow_path(ret == NXT_ERROR)) {
+ nxt_exiting = 1;
+
+ nxt_runtime_quit(task, 1);
}
}
@@ -1534,362 +1346,3 @@ nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
msg->port_msg.stream, 0, NULL);
}
}
-
-
-static nxt_int_t
-nxt_init_isolation(nxt_task_t *task, nxt_conf_value_t *isolation,
- nxt_process_init_t *init)
-{
-#if (NXT_HAVE_CLONE)
- nxt_int_t ret;
- nxt_conf_value_t *obj;
-
- static nxt_str_t nsname = nxt_string("namespaces");
-
- obj = nxt_conf_get_object_member(isolation, &nsname, NULL);
- if (obj != NULL) {
- ret = nxt_init_clone_flags(task, obj, init);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
- }
- }
-#endif
-
-#if (NXT_HAVE_CLONE_NEWUSER)
- ret = nxt_init_isolation_creds(task, isolation, init);
- if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
- }
-#endif
-
- return NXT_OK;
-}
-
-
-#if (NXT_HAVE_CLONE_NEWUSER)
-
-static nxt_int_t
-nxt_init_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation,
- nxt_process_init_t *init)
-{
- nxt_int_t ret;
- nxt_clone_t *clone;
- nxt_conf_value_t *array;
-
- static nxt_str_t uidname = nxt_string("uidmap");
- static nxt_str_t gidname = nxt_string("gidmap");
-
- clone = &init->isolation.clone;
-
- array = nxt_conf_get_object_member(isolation, &uidname, NULL);
- if (array != NULL) {
- ret = nxt_init_isolation_credential_map(task, init->mem_pool, array,
- &clone->uidmap);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
- }
- }
-
- array = nxt_conf_get_object_member(isolation, &gidname, NULL);
- if (array != NULL) {
- ret = nxt_init_isolation_credential_map(task, init->mem_pool, array,
- &clone->gidmap);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
- }
- }
-
- return NXT_OK;
-}
-
-
-static nxt_int_t
-nxt_init_vldt_isolation_creds(nxt_task_t *task, nxt_process_init_t *init)
-{
- nxt_int_t ret;
- nxt_clone_t *clone;
-
- clone = &init->isolation.clone;
-
- if (clone->uidmap.size == 0 && clone->gidmap.size == 0) {
- return NXT_OK;
- }
-
- if (!NXT_CLONE_USER(clone->flags)) {
- if (nxt_slow_path(clone->uidmap.size > 0)) {
- nxt_log(task, NXT_LOG_ERR, "\"uidmap\" is set but "
- "\"isolation.namespaces.credential\" is false or unset");
-
- return NXT_ERROR;
- }
-
- if (nxt_slow_path(clone->gidmap.size > 0)) {
- nxt_log(task, NXT_LOG_ERR, "\"gidmap\" is set but "
- "\"isolation.namespaces.credential\" is false or unset");
-
- return NXT_ERROR;
- }
-
- return NXT_OK;
- }
-
- ret = nxt_clone_vldt_credential_uidmap(task, &clone->uidmap,
- init->user_cred);
-
- if (nxt_slow_path(ret != NXT_OK)) {
- return NXT_ERROR;
- }
-
- return nxt_clone_vldt_credential_gidmap(task, &clone->gidmap,
- init->user_cred);
-}
-
-
-static nxt_int_t
-nxt_init_isolation_credential_map(nxt_task_t *task, nxt_mp_t *mem_pool,
- nxt_conf_value_t *map_array, nxt_clone_credential_map_t *map)
-{
- nxt_int_t ret;
- nxt_uint_t i;
- nxt_conf_value_t *obj;
-
- static nxt_conf_map_t nxt_clone_map_entry_conf[] = {
- {
- nxt_string("container"),
- NXT_CONF_MAP_INT,
- offsetof(nxt_clone_map_entry_t, container),
- },
-
- {
- nxt_string("host"),
- NXT_CONF_MAP_INT,
- offsetof(nxt_clone_map_entry_t, host),
- },
-
- {
- nxt_string("size"),
- NXT_CONF_MAP_INT,
- offsetof(nxt_clone_map_entry_t, size),
- },
- };
-
- map->size = nxt_conf_array_elements_count(map_array);
-
- if (map->size == 0) {
- return NXT_OK;
- }
-
- map->map = nxt_mp_alloc(mem_pool,
- map->size * sizeof(nxt_clone_map_entry_t));
- if (nxt_slow_path(map->map == NULL)) {
- return NXT_ERROR;
- }
-
- for (i = 0; i < map->size; i++) {
- obj = nxt_conf_get_array_element(map_array, i);
-
- ret = nxt_conf_map_object(mem_pool, obj, nxt_clone_map_entry_conf,
- nxt_nitems(nxt_clone_map_entry_conf),
- map->map + i);
- if (nxt_slow_path(ret != NXT_OK)) {
- nxt_alert(task, "clone map entry map error");
- return NXT_ERROR;
- }
- }
-
- return NXT_OK;
-}
-
-#endif
-
-#if (NXT_HAVE_CLONE)
-
-static nxt_int_t
-nxt_init_clone_flags(nxt_task_t *task, nxt_conf_value_t *namespaces,
- nxt_process_init_t *init)
-{
- uint32_t index;
- nxt_str_t name;
- nxt_int_t flag;
- nxt_conf_value_t *value;
-
- index = 0;
-
- for ( ;; ) {
- value = nxt_conf_next_object_member(namespaces, &name, &index);
-
- if (value == NULL) {
- break;
- }
-
- flag = 0;
-
-#if (NXT_HAVE_CLONE_NEWUSER)
- if (nxt_str_eq(&name, "credential", 10)) {
- flag = CLONE_NEWUSER;
- }
-#endif
-
-#if (NXT_HAVE_CLONE_NEWPID)
- if (nxt_str_eq(&name, "pid", 3)) {
- flag = CLONE_NEWPID;
- }
-#endif
-
-#if (NXT_HAVE_CLONE_NEWNET)
- if (nxt_str_eq(&name, "network", 7)) {
- flag = CLONE_NEWNET;
- }
-#endif
-
-#if (NXT_HAVE_CLONE_NEWUTS)
- if (nxt_str_eq(&name, "uname", 5)) {
- flag = CLONE_NEWUTS;
- }
-#endif
-
-#if (NXT_HAVE_CLONE_NEWNS)
- if (nxt_str_eq(&name, "mount", 5)) {
- flag = CLONE_NEWNS;
- }
-#endif
-
-#if (NXT_HAVE_CLONE_NEWCGROUP)
- if (nxt_str_eq(&name, "cgroup", 6)) {
- flag = CLONE_NEWCGROUP;
- }
-#endif
-
- if (!flag) {
- nxt_alert(task, "unknown namespace flag: \"%V\"", &name);
- return NXT_ERROR;
- }
-
- if (nxt_conf_get_boolean(value)) {
- init->isolation.clone.flags |= flag;
- }
- }
-
- return NXT_OK;
-}
-
-#endif
-
-
-static nxt_process_init_t *
-nxt_process_init_create(nxt_task_t *task, nxt_process_type_t type,
- const nxt_str_t *name)
-{
- nxt_mp_t *mp;
- nxt_int_t ret;
- nxt_runtime_t *rt;
- nxt_process_init_t *init;
-
- mp = nxt_mp_create(1024, 128, 256, 32);
- if (nxt_slow_path(mp == NULL)) {
- return NULL;
- }
-
- init = nxt_mp_zalloc(mp, sizeof(nxt_process_init_t));
- if (nxt_slow_path(init == NULL)) {
- goto fail;
- }
-
- init->mem_pool = mp;
-
- ret = nxt_process_init_name_set(init, type, name);
- if (nxt_slow_path(ret != NXT_OK)) {
- goto fail;
- }
-
- rt = task->thread->runtime;
-
- init->type = type;
- init->start = nxt_process_starts[type];
- init->port_handlers = nxt_process_port_handlers[type];
- init->signals = nxt_worker_process_signals;
- init->user_cred = &rt->user_cred;
- init->data = &rt;
-
- return init;
-
-fail:
-
- nxt_mp_destroy(mp);
-
- return NULL;
-}
-
-
-static nxt_int_t
-nxt_process_init_name_set(nxt_process_init_t *init, nxt_process_type_t type,
- const nxt_str_t *name)
-{
- u_char *str, *end;
- size_t size;
- const char *fmt;
-
- size = name->length + 1;
-
- if (type == NXT_PROCESS_WORKER) {
- size += nxt_length("\"\" application");
- fmt = "\"%V\" application%Z";
-
- } else {
- fmt = "%V%Z";
- }
-
- str = nxt_mp_alloc(init->mem_pool, size);
- if (nxt_slow_path(str == NULL)) {
- return NXT_ERROR;
- }
-
- end = str + size;
-
- nxt_sprintf(str, end, fmt, name);
-
- init->name = (char *) str;
-
- return NXT_OK;
-}
-
-
-static nxt_int_t
-nxt_process_init_creds_set(nxt_task_t *task, nxt_process_init_t *init,
- nxt_str_t *user, nxt_str_t *group)
-{
- char *str;
-
- init->user_cred = nxt_mp_zalloc(init->mem_pool, sizeof(nxt_credential_t));
-
- if (nxt_slow_path(init->user_cred == NULL)) {
- return NXT_ERROR;
- }
-
- str = nxt_mp_zalloc(init->mem_pool, user->length + 1);
- if (nxt_slow_path(str == NULL)) {
- return NXT_ERROR;
- }
-
- nxt_memcpy(str, user->start, user->length);
- str[user->length] = '\0';
-
- init->user_cred->user = str;
-
- if (group->start != NULL) {
- str = nxt_mp_zalloc(init->mem_pool, group->length + 1);
- if (nxt_slow_path(str == NULL)) {
- return NXT_ERROR;
- }
-
- nxt_memcpy(str, group->start, group->length);
- str[group->length] = '\0';
-
- } else {
- str = NULL;
- }
-
- return nxt_credential_get(task, init->mem_pool, init->user_cred, str);
-}
diff --git a/src/nxt_main_process.h b/src/nxt_main_process.h
index b0570a84..f9c974d8 100644
--- a/src/nxt_main_process.h
+++ b/src/nxt_main_process.h
@@ -19,26 +19,17 @@ typedef enum {
} nxt_socket_error_t;
-typedef struct {
- nxt_str_t conf;
-#if (NXT_TLS)
- nxt_array_t *certs;
-#endif
-} nxt_controller_init_t;
-
-
nxt_int_t nxt_main_process_start(nxt_thread_t *thr, nxt_task_t *task,
nxt_runtime_t *runtime);
-void nxt_main_stop_all_processes(nxt_task_t *task, nxt_runtime_t *runtime);
-nxt_int_t nxt_controller_start(nxt_task_t *task, void *data);
-nxt_int_t nxt_router_start(nxt_task_t *task, void *data);
-nxt_int_t nxt_discovery_start(nxt_task_t *task, void *data);
-nxt_int_t nxt_app_start(nxt_task_t *task, void *data);
+NXT_EXPORT extern const nxt_process_init_t nxt_discovery_process;
+NXT_EXPORT extern const nxt_process_init_t nxt_controller_process;
+NXT_EXPORT extern const nxt_process_init_t nxt_router_process;
+NXT_EXPORT extern const nxt_process_init_t nxt_app_process;
extern const nxt_sig_event_t nxt_main_process_signals[];
-extern const nxt_sig_event_t nxt_worker_process_signals[];
+extern const nxt_sig_event_t nxt_process_signals[];
#endif /* _NXT_MAIN_PROCESS_H_INCLUDED_ */
diff --git a/src/nxt_php_sapi.c b/src/nxt_php_sapi.c
index d3c23c31..ddad5761 100644
--- a/src/nxt_php_sapi.c
+++ b/src/nxt_php_sapi.c
@@ -72,7 +72,7 @@ typedef void (*zif_handler)(INTERNAL_FUNCTION_PARAMETERS);
#endif
-static nxt_int_t nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
+static nxt_int_t nxt_php_start(nxt_task_t *task, nxt_process_data_t *data);
static nxt_int_t nxt_php_set_target(nxt_task_t *task, nxt_php_target_t *target,
nxt_conf_value_t *conf);
static void nxt_php_set_options(nxt_task_t *task, nxt_conf_value_t *options,
@@ -242,7 +242,7 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
nxt_string("php"),
PHP_VERSION,
NULL,
- nxt_php_init,
+ nxt_php_start,
};
@@ -256,19 +256,20 @@ static void ***tsrm_ls;
static nxt_int_t
-nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
+nxt_php_start(nxt_task_t *task, nxt_process_data_t *data)
{
- u_char *p;
- uint32_t next;
- nxt_str_t ini_path, name;
- nxt_int_t ret;
- nxt_uint_t n;
- nxt_port_t *my_port, *main_port;
- nxt_runtime_t *rt;
- nxt_unit_ctx_t *unit_ctx;
- nxt_unit_init_t php_init;
- nxt_conf_value_t *value;
- nxt_php_app_conf_t *c;
+ u_char *p;
+ uint32_t next;
+ nxt_str_t ini_path, name;
+ nxt_int_t ret;
+ nxt_uint_t n;
+ nxt_port_t *my_port, *main_port;
+ nxt_runtime_t *rt;
+ nxt_unit_ctx_t *unit_ctx;
+ nxt_unit_init_t php_init;
+ nxt_conf_value_t *value;
+ nxt_php_app_conf_t *c;
+ nxt_common_app_conf_t *conf;
static nxt_str_t file_str = nxt_string("file");
static nxt_str_t user_str = nxt_string("user");
@@ -276,6 +277,7 @@ nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
nxt_php_task = task;
+ conf = data->app;
c = &conf->u.php;
n = (c->targets != NULL) ? nxt_conf_object_members_count(c->targets) : 1;
@@ -385,7 +387,7 @@ nxt_php_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
nxt_fd_blocking(task, main_port->pair[1]);
- php_init.ready_stream = my_port->process->init->stream;
+ php_init.ready_stream = my_port->process->stream;
php_init.read_port.id.pid = my_port->pid;
php_init.read_port.id.id = my_port->id;
diff --git a/src/nxt_port.c b/src/nxt_port.c
index 70cf33e6..7232c465 100644
--- a/src/nxt_port.c
+++ b/src/nxt_port.c
@@ -296,7 +296,9 @@ nxt_port_process_ready_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
return;
}
- process->ready = 1;
+ nxt_assert(process->state != NXT_PROCESS_STATE_READY);
+
+ process->state = NXT_PROCESS_STATE_READY;
nxt_assert(!nxt_queue_is_empty(&process->ports));
diff --git a/src/nxt_port.h b/src/nxt_port.h
index c6f15238..0e8707f3 100644
--- a/src/nxt_port.h
+++ b/src/nxt_port.h
@@ -14,7 +14,7 @@ struct nxt_port_handlers_s {
nxt_port_handler_t rpc_error;
/* Main process RPC requests. */
- nxt_port_handler_t start_worker;
+ nxt_port_handler_t start_process;
nxt_port_handler_t socket;
nxt_port_handler_t modules;
nxt_port_handler_t conf_store;
@@ -27,7 +27,8 @@ struct nxt_port_handlers_s {
nxt_port_handler_t new_port;
nxt_port_handler_t mmap;
- /* New process ready. */
+ /* New process */
+ nxt_port_handler_t process_created;
nxt_port_handler_t process_ready;
/* Process exit/crash notification. */
@@ -53,76 +54,76 @@ struct nxt_port_handlers_s {
#define nxt_port_handler_idx(name) \
( offsetof(nxt_port_handlers_t, name) / sizeof(nxt_port_handler_t) )
+#define nxt_msg_last(handler) \
+ (handler | NXT_PORT_MSG_LAST)
typedef enum {
- NXT_PORT_MSG_LAST = 0x100,
- NXT_PORT_MSG_CLOSE_FD = 0x200,
- NXT_PORT_MSG_SYNC = 0x400,
-
- NXT_PORT_MSG_MASK = 0xFF,
-
- _NXT_PORT_MSG_RPC_READY = nxt_port_handler_idx(rpc_ready),
- _NXT_PORT_MSG_RPC_ERROR = nxt_port_handler_idx(rpc_error),
-
- _NXT_PORT_MSG_START_WORKER = nxt_port_handler_idx(start_worker),
- _NXT_PORT_MSG_SOCKET = nxt_port_handler_idx(socket),
- _NXT_PORT_MSG_MODULES = nxt_port_handler_idx(modules),
- _NXT_PORT_MSG_CONF_STORE = nxt_port_handler_idx(conf_store),
- _NXT_PORT_MSG_CERT_GET = nxt_port_handler_idx(cert_get),
- _NXT_PORT_MSG_CERT_DELETE = nxt_port_handler_idx(cert_delete),
- _NXT_PORT_MSG_ACCESS_LOG = nxt_port_handler_idx(access_log),
-
- _NXT_PORT_MSG_CHANGE_FILE = nxt_port_handler_idx(change_file),
- _NXT_PORT_MSG_NEW_PORT = nxt_port_handler_idx(new_port),
- _NXT_PORT_MSG_MMAP = nxt_port_handler_idx(mmap),
-
- _NXT_PORT_MSG_PROCESS_READY = nxt_port_handler_idx(process_ready),
- _NXT_PORT_MSG_REMOVE_PID = nxt_port_handler_idx(remove_pid),
- _NXT_PORT_MSG_QUIT = nxt_port_handler_idx(quit),
-
- _NXT_PORT_MSG_REQ_HEADERS = nxt_port_handler_idx(req_headers),
- _NXT_PORT_MSG_WEBSOCKET = nxt_port_handler_idx(websocket_frame),
-
- _NXT_PORT_MSG_DATA = nxt_port_handler_idx(data),
-
- _NXT_PORT_MSG_OOSM = nxt_port_handler_idx(oosm),
- _NXT_PORT_MSG_SHM_ACK = nxt_port_handler_idx(shm_ack),
-
- NXT_PORT_MSG_MAX = sizeof(nxt_port_handlers_t)
- / sizeof(nxt_port_handler_t),
-
- NXT_PORT_MSG_RPC_READY = _NXT_PORT_MSG_RPC_READY,
- NXT_PORT_MSG_RPC_READY_LAST = _NXT_PORT_MSG_RPC_READY | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_RPC_ERROR = _NXT_PORT_MSG_RPC_ERROR | NXT_PORT_MSG_LAST,
-
- NXT_PORT_MSG_START_WORKER = _NXT_PORT_MSG_START_WORKER
- | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_SOCKET = _NXT_PORT_MSG_SOCKET | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_MODULES = _NXT_PORT_MSG_MODULES | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_CONF_STORE = _NXT_PORT_MSG_CONF_STORE | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_CERT_GET = _NXT_PORT_MSG_CERT_GET | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_CERT_DELETE = _NXT_PORT_MSG_CERT_DELETE | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_ACCESS_LOG = _NXT_PORT_MSG_ACCESS_LOG | NXT_PORT_MSG_LAST,
-
- NXT_PORT_MSG_CHANGE_FILE = _NXT_PORT_MSG_CHANGE_FILE | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_NEW_PORT = _NXT_PORT_MSG_NEW_PORT | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_MMAP = _NXT_PORT_MSG_MMAP | NXT_PORT_MSG_LAST
- | NXT_PORT_MSG_CLOSE_FD | NXT_PORT_MSG_SYNC,
-
- NXT_PORT_MSG_PROCESS_READY = _NXT_PORT_MSG_PROCESS_READY
- | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_QUIT = _NXT_PORT_MSG_QUIT | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_REMOVE_PID = _NXT_PORT_MSG_REMOVE_PID | NXT_PORT_MSG_LAST,
-
- NXT_PORT_MSG_REQ_HEADERS = _NXT_PORT_MSG_REQ_HEADERS,
- NXT_PORT_MSG_WEBSOCKET = _NXT_PORT_MSG_WEBSOCKET,
- NXT_PORT_MSG_WEBSOCKET_LAST = _NXT_PORT_MSG_WEBSOCKET | NXT_PORT_MSG_LAST,
-
- NXT_PORT_MSG_DATA = _NXT_PORT_MSG_DATA,
- NXT_PORT_MSG_DATA_LAST = _NXT_PORT_MSG_DATA | NXT_PORT_MSG_LAST,
-
- NXT_PORT_MSG_OOSM = _NXT_PORT_MSG_OOSM | NXT_PORT_MSG_LAST,
- NXT_PORT_MSG_SHM_ACK = _NXT_PORT_MSG_SHM_ACK | NXT_PORT_MSG_LAST,
+ NXT_PORT_MSG_LAST = 0x100,
+ NXT_PORT_MSG_CLOSE_FD = 0x200,
+ NXT_PORT_MSG_SYNC = 0x400,
+
+ NXT_PORT_MSG_MASK = 0xFF,
+
+ _NXT_PORT_MSG_RPC_READY = nxt_port_handler_idx(rpc_ready),
+ _NXT_PORT_MSG_RPC_ERROR = nxt_port_handler_idx(rpc_error),
+
+ _NXT_PORT_MSG_START_PROCESS = nxt_port_handler_idx(start_process),
+ _NXT_PORT_MSG_SOCKET = nxt_port_handler_idx(socket),
+ _NXT_PORT_MSG_MODULES = nxt_port_handler_idx(modules),
+ _NXT_PORT_MSG_CONF_STORE = nxt_port_handler_idx(conf_store),
+ _NXT_PORT_MSG_CERT_GET = nxt_port_handler_idx(cert_get),
+ _NXT_PORT_MSG_CERT_DELETE = nxt_port_handler_idx(cert_delete),
+ _NXT_PORT_MSG_ACCESS_LOG = nxt_port_handler_idx(access_log),
+
+ _NXT_PORT_MSG_CHANGE_FILE = nxt_port_handler_idx(change_file),
+ _NXT_PORT_MSG_NEW_PORT = nxt_port_handler_idx(new_port),
+ _NXT_PORT_MSG_MMAP = nxt_port_handler_idx(mmap),
+
+ _NXT_PORT_MSG_PROCESS_CREATED = nxt_port_handler_idx(process_created),
+ _NXT_PORT_MSG_PROCESS_READY = nxt_port_handler_idx(process_ready),
+ _NXT_PORT_MSG_REMOVE_PID = nxt_port_handler_idx(remove_pid),
+ _NXT_PORT_MSG_QUIT = nxt_port_handler_idx(quit),
+
+ _NXT_PORT_MSG_REQ_HEADERS = nxt_port_handler_idx(req_headers),
+ _NXT_PORT_MSG_WEBSOCKET = nxt_port_handler_idx(websocket_frame),
+
+ _NXT_PORT_MSG_DATA = nxt_port_handler_idx(data),
+
+ _NXT_PORT_MSG_OOSM = nxt_port_handler_idx(oosm),
+ _NXT_PORT_MSG_SHM_ACK = nxt_port_handler_idx(shm_ack),
+
+ NXT_PORT_MSG_MAX = sizeof(nxt_port_handlers_t)
+ / sizeof(nxt_port_handler_t),
+
+ NXT_PORT_MSG_RPC_READY = _NXT_PORT_MSG_RPC_READY,
+ NXT_PORT_MSG_RPC_READY_LAST = nxt_msg_last(_NXT_PORT_MSG_RPC_READY),
+ NXT_PORT_MSG_RPC_ERROR = nxt_msg_last(_NXT_PORT_MSG_RPC_ERROR),
+ NXT_PORT_MSG_START_PROCESS = nxt_msg_last(_NXT_PORT_MSG_START_PROCESS),
+ NXT_PORT_MSG_SOCKET = nxt_msg_last(_NXT_PORT_MSG_SOCKET),
+ NXT_PORT_MSG_MODULES = nxt_msg_last(_NXT_PORT_MSG_MODULES),
+ NXT_PORT_MSG_CONF_STORE = nxt_msg_last(_NXT_PORT_MSG_CONF_STORE),
+ NXT_PORT_MSG_CERT_GET = nxt_msg_last(_NXT_PORT_MSG_CERT_GET),
+ NXT_PORT_MSG_CERT_DELETE = nxt_msg_last(_NXT_PORT_MSG_CERT_DELETE),
+ NXT_PORT_MSG_ACCESS_LOG = nxt_msg_last(_NXT_PORT_MSG_ACCESS_LOG),
+ NXT_PORT_MSG_CHANGE_FILE = nxt_msg_last(_NXT_PORT_MSG_CHANGE_FILE),
+ NXT_PORT_MSG_NEW_PORT = nxt_msg_last(_NXT_PORT_MSG_NEW_PORT),
+ NXT_PORT_MSG_MMAP = nxt_msg_last(_NXT_PORT_MSG_MMAP)
+ | NXT_PORT_MSG_CLOSE_FD | NXT_PORT_MSG_SYNC,
+
+ NXT_PORT_MSG_PROCESS_CREATED = nxt_msg_last(_NXT_PORT_MSG_PROCESS_CREATED),
+ NXT_PORT_MSG_PROCESS_READY = nxt_msg_last(_NXT_PORT_MSG_PROCESS_READY),
+ NXT_PORT_MSG_QUIT = nxt_msg_last(_NXT_PORT_MSG_QUIT),
+ NXT_PORT_MSG_REMOVE_PID = nxt_msg_last(_NXT_PORT_MSG_REMOVE_PID),
+
+ NXT_PORT_MSG_REQ_HEADERS = _NXT_PORT_MSG_REQ_HEADERS,
+ NXT_PORT_MSG_WEBSOCKET = _NXT_PORT_MSG_WEBSOCKET,
+ NXT_PORT_MSG_WEBSOCKET_LAST = nxt_msg_last(_NXT_PORT_MSG_WEBSOCKET),
+
+ NXT_PORT_MSG_DATA = _NXT_PORT_MSG_DATA,
+ NXT_PORT_MSG_DATA_LAST = nxt_msg_last(_NXT_PORT_MSG_DATA),
+
+ NXT_PORT_MSG_OOSM = nxt_msg_last(_NXT_PORT_MSG_OOSM),
+ NXT_PORT_MSG_SHM_ACK = nxt_msg_last(_NXT_PORT_MSG_SHM_ACK),
} nxt_port_msg_type_t;
diff --git a/src/nxt_port_memory.c b/src/nxt_port_memory.c
index 33d3777e..f4d2125c 100644
--- a/src/nxt_port_memory.c
+++ b/src/nxt_port_memory.c
@@ -174,7 +174,7 @@ complete_buf:
if (process != NULL && !nxt_queue_is_empty(&process->ports)) {
port = nxt_process_port_first(process);
- if (port->type == NXT_PROCESS_WORKER) {
+ if (port->type == NXT_PROCESS_APP) {
(void) nxt_port_socket_write(task, port, NXT_PORT_MSG_SHM_ACK,
-1, 0, 0, NULL);
}
diff --git a/src/nxt_process.c b/src/nxt_process.c
index f5959edf..e84549b3 100644
--- a/src/nxt_process.c
+++ b/src/nxt_process.c
@@ -13,9 +13,18 @@
#include <signal.h>
-static void nxt_process_start(nxt_task_t *task, nxt_process_t *process);
-static nxt_int_t nxt_process_worker_setup(nxt_task_t *task,
- nxt_process_t *process, int parentfd);
+static nxt_int_t nxt_process_setup(nxt_task_t *task, nxt_process_t *process);
+static nxt_int_t nxt_process_child_fixup(nxt_task_t *task,
+ nxt_process_t *process);
+static nxt_int_t nxt_process_send_created(nxt_task_t *task,
+ nxt_process_t *process);
+static nxt_int_t nxt_process_send_ready(nxt_task_t *task,
+ nxt_process_t *process);
+static void nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data);
+static void nxt_process_created_error(nxt_task_t *task,
+ nxt_port_recv_msg_t *msg, void *data);
+
/* A cached process pid. */
nxt_pid_t nxt_pid;
@@ -47,62 +56,58 @@ nxt_bool_t nxt_proc_remove_notify_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX] = {
static nxt_int_t
-nxt_process_worker_setup(nxt_task_t *task, nxt_process_t *process, int parentfd)
+nxt_process_child_fixup(nxt_task_t *task, nxt_process_t *process)
{
- pid_t rpid, pid;
- ssize_t n;
- nxt_int_t parent_status;
nxt_process_t *p;
nxt_runtime_t *rt;
nxt_process_init_t *init;
nxt_process_type_t ptype;
- pid = getpid();
- rpid = 0;
- rt = task->thread->runtime;
- init = process->init;
+ init = nxt_process_init(process);
- /* Setup the worker process. */
+ nxt_pid = nxt_getpid();
- n = read(parentfd, &rpid, sizeof(rpid));
- if (nxt_slow_path(n == -1 || n != sizeof(rpid))) {
- nxt_alert(task, "failed to read real pid");
- return NXT_ERROR;
- }
-
- if (nxt_slow_path(rpid == 0)) {
- nxt_alert(task, "failed to get real pid from parent");
- return NXT_ERROR;
- }
-
- nxt_pid = rpid;
+ process->pid = nxt_pid;
/* Clean inherited cached thread tid. */
task->thread->tid = 0;
- process->pid = nxt_pid;
+#if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWPID)
+ if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWPID)) {
+ ssize_t pidsz;
+ char procpid[10];
- if (nxt_pid != pid) {
- nxt_debug(task, "app \"%s\" real pid %d", init->name, nxt_pid);
- nxt_debug(task, "app \"%s\" isolated pid: %d", init->name, pid);
- }
+ nxt_debug(task, "%s isolated pid is %d", process->name, nxt_pid);
- n = read(parentfd, &parent_status, sizeof(parent_status));
- if (nxt_slow_path(n == -1 || n != sizeof(parent_status))) {
- nxt_alert(task, "failed to read parent status");
- return NXT_ERROR;
- }
+ pidsz = readlink("/proc/self", procpid, sizeof(procpid));
+
+ if (nxt_slow_path(pidsz < 0 || pidsz >= (ssize_t) sizeof(procpid))) {
+ nxt_alert(task, "failed to read real pid from /proc/self");
+ return NXT_ERROR;
+ }
+
+ procpid[pidsz] = '\0';
+
+ nxt_pid = (nxt_pid_t) strtol(procpid, NULL, 10);
+
+ nxt_assert(nxt_pid > 0 && nxt_errno != ERANGE);
- if (nxt_slow_path(parent_status != NXT_OK)) {
- return parent_status;
+ process->pid = nxt_pid;
+ task->thread->tid = nxt_pid;
+
+ nxt_debug(task, "%s real pid is %d", process->name, nxt_pid);
}
+#endif
+
ptype = init->type;
nxt_port_reset_next_id();
nxt_event_engine_thread_adopt(task->thread->engine);
+ rt = task->thread->runtime;
+
/* Remove not ready processes. */
nxt_runtime_process_each(rt, p) {
@@ -114,7 +119,7 @@ nxt_process_worker_setup(nxt_task_t *task, nxt_process_t *process, int parentfd)
continue;
}
- if (!p->ready) {
+ if (p->state != NXT_PROCESS_STATE_READY) {
nxt_debug(task, "remove not ready process %PI", p->pid);
nxt_process_close_ports(task, p);
@@ -127,12 +132,6 @@ nxt_process_worker_setup(nxt_task_t *task, nxt_process_t *process, int parentfd)
} nxt_runtime_process_loop;
- nxt_runtime_process_add(task, process);
-
- nxt_process_start(task, process);
-
- process->ready = 1;
-
return NXT_OK;
}
@@ -140,48 +139,36 @@ nxt_process_worker_setup(nxt_task_t *task, nxt_process_t *process, int parentfd)
nxt_pid_t
nxt_process_create(nxt_task_t *task, nxt_process_t *process)
{
- int pipefd[2];
nxt_int_t ret;
nxt_pid_t pid;
- nxt_process_init_t *init;
-
- if (nxt_slow_path(pipe(pipefd) == -1)) {
- nxt_alert(task, "failed to create process pipe for passing rpid");
- return -1;
- }
-
- init = process->init;
#if (NXT_HAVE_CLONE)
- pid = nxt_clone(SIGCHLD | init->isolation.clone.flags);
+ pid = nxt_clone(SIGCHLD | process->isolation.clone.flags);
if (nxt_slow_path(pid < 0)) {
- nxt_alert(task, "clone() failed while creating \"%s\" %E",
- init->name, nxt_errno);
- goto cleanup;
+ nxt_alert(task, "clone() failed for %s %E", process->name, nxt_errno);
+ return pid;
}
#else
pid = fork();
if (nxt_slow_path(pid < 0)) {
- nxt_alert(task, "fork() failed while creating \"%s\" %E",
- init->name, nxt_errno);
- goto cleanup;
+ nxt_alert(task, "fork() failed for %s %E", process->name, nxt_errno);
+ return pid;
}
#endif
if (pid == 0) {
/* Child. */
- if (nxt_slow_path(close(pipefd[1]) == -1)) {
- nxt_alert(task, "failed to close writer pipe fd");
- }
-
- ret = nxt_process_worker_setup(task, process, pipefd[0]);
+ ret = nxt_process_child_fixup(task, process);
if (nxt_slow_path(ret != NXT_OK)) {
- exit(1);
+ nxt_process_quit(task, 1);
+ return -1;
}
- if (nxt_slow_path(close(pipefd[0]) == -1)) {
- nxt_alert(task, "failed to close writer pipe fd");
+ nxt_runtime_process_add(task, process);
+
+ if (nxt_slow_path(nxt_process_setup(task, process) != NXT_OK)) {
+ nxt_process_quit(task, 1);
}
/*
@@ -193,78 +180,24 @@ nxt_process_create(nxt_task_t *task, nxt_process_t *process)
/* Parent. */
- /*
- * At this point, the child process is blocked reading the
- * pipe fd to get its real pid (rpid).
- *
- * If anything goes wrong now, we need to terminate the child
- * process by sending a NXT_ERROR in the pipe.
- */
-
#if (NXT_HAVE_CLONE)
- nxt_debug(task, "clone(\"%s\"): %PI", init->name, pid);
+ nxt_debug(task, "clone(%s): %PI", process->name, pid);
#else
- nxt_debug(task, "fork(\"%s\"): %PI", init->name, pid);
+ nxt_debug(task, "fork(%s): %PI", process->name, pid);
#endif
- if (nxt_slow_path(write(pipefd[1], &pid, sizeof(pid)) == -1)) {
- nxt_alert(task, "failed to write real pid");
- goto fail;
- }
-
-#if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER)
- if (NXT_CLONE_USER(init->isolation.clone.flags)) {
- ret = nxt_clone_credential_map(task, pid, init->user_cred,
- &init->isolation.clone);
- if (nxt_slow_path(ret != NXT_OK)) {
- goto fail;
- }
- }
-#endif
-
- ret = NXT_OK;
-
- if (nxt_slow_path(write(pipefd[1], &ret, sizeof(ret)) == -1)) {
- nxt_alert(task, "failed to write status");
- goto fail;
- }
-
process->pid = pid;
nxt_runtime_process_add(task, process);
- goto cleanup;
-
-fail:
-
- ret = NXT_ERROR;
-
- if (nxt_slow_path(write(pipefd[1], &ret, sizeof(ret)) == -1)) {
- nxt_alert(task, "failed to write status");
- }
-
- waitpid(pid, NULL, 0);
-
- pid = -1;
-
-cleanup:
-
- if (nxt_slow_path(close(pipefd[0]) != 0)) {
- nxt_alert(task, "failed to close pipe: %E", nxt_errno);
- }
-
- if (nxt_slow_path(close(pipefd[1]) != 0)) {
- nxt_alert(task, "failed to close pipe: %E", nxt_errno);
- }
-
return pid;
}
-static void
-nxt_process_start(nxt_task_t *task, nxt_process_t *process)
+static nxt_int_t
+nxt_process_setup(nxt_task_t *task, nxt_process_t *process)
{
- nxt_int_t ret, cap_setid;
+ nxt_int_t ret;
nxt_port_t *port, *main_port;
nxt_thread_t *thread;
nxt_runtime_t *rt;
@@ -272,37 +205,17 @@ nxt_process_start(nxt_task_t *task, nxt_process_t *process)
nxt_event_engine_t *engine;
const nxt_event_interface_t *interface;
- init = process->init;
+ init = nxt_process_init(process);
- nxt_log(task, NXT_LOG_INFO, "%s started", init->name);
+ nxt_debug(task, "%s setup", process->name);
- nxt_process_title(task, "unit: %s", init->name);
+ nxt_process_title(task, "unit: %s", process->name);
thread = task->thread;
rt = thread->runtime;
nxt_random_init(&thread->random);
- cap_setid = rt->capabilities.setid;
-
-#if (NXT_HAVE_CLONE_NEWUSER)
- if (!cap_setid && NXT_CLONE_USER(init->isolation.clone.flags)) {
- cap_setid = 1;
- }
-#endif
-
- if (cap_setid) {
- ret = nxt_credential_setgids(task, init->user_cred);
- if (nxt_slow_path(ret != NXT_OK)) {
- goto fail;
- }
-
- ret = nxt_credential_setuid(task, init->user_cred);
- if (nxt_slow_path(ret != NXT_OK)) {
- goto fail;
- }
- }
-
rt->type = init->type;
engine = thread->engine;
@@ -312,17 +225,17 @@ nxt_process_start(nxt_task_t *task, nxt_process_t *process)
interface = nxt_service_get(rt->services, "engine", rt->engine);
if (nxt_slow_path(interface == NULL)) {
- goto fail;
+ return NXT_ERROR;
}
if (nxt_event_engine_change(engine, interface, rt->batch) != NXT_OK) {
- goto fail;
+ return NXT_ERROR;
}
ret = nxt_runtime_thread_pool_create(thread, rt, rt->auxiliary_threads,
60000 * 1000000LL);
if (nxt_slow_path(ret != NXT_OK)) {
- goto fail;
+ return NXT_ERROR;
}
main_port = rt->port_by_type[NXT_PROCESS_MAIN];
@@ -334,28 +247,282 @@ nxt_process_start(nxt_task_t *task, nxt_process_t *process)
nxt_port_write_close(port);
- ret = init->start(task, init->data);
+ nxt_port_enable(task, port, init->port_handlers);
+
+ ret = init->setup(task, process);
if (nxt_slow_path(ret != NXT_OK)) {
- goto fail;
+ return NXT_ERROR;
}
- nxt_port_enable(task, port, init->port_handlers);
+ switch (process->state) {
- ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_PROCESS_READY,
- -1, init->stream, 0, NULL);
+ case NXT_PROCESS_STATE_CREATED:
+ ret = nxt_process_send_created(task, process);
+ break;
+
+ case NXT_PROCESS_STATE_READY:
+ ret = nxt_process_send_ready(task, process);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ break;
+ }
+
+ ret = init->start(task, &process->data);
+ break;
+
+ default:
+ nxt_assert(0);
+ }
if (nxt_slow_path(ret != NXT_OK)) {
- nxt_log(task, NXT_LOG_ERR, "failed to send READY message to main");
+ nxt_alert(task, "%s failed to start", process->name);
+ }
+
+ return ret;
+}
+
+static nxt_int_t
+nxt_process_send_created(nxt_task_t *task, nxt_process_t *process)
+{
+ uint32_t stream;
+ nxt_int_t ret;
+ nxt_port_t *my_port, *main_port;
+ nxt_runtime_t *rt;
+
+ nxt_assert(process->state == NXT_PROCESS_STATE_CREATED);
+
+ rt = task->thread->runtime;
+
+ my_port = nxt_process_port_first(process);
+ main_port = rt->port_by_type[NXT_PROCESS_MAIN];
+
+ nxt_assert(my_port != NULL && main_port != NULL);
+
+ stream = nxt_port_rpc_register_handler(task, my_port,
+ nxt_process_created_ok,
+ nxt_process_created_error,
+ main_port->pid, process);
+
+ if (nxt_slow_path(stream == 0)) {
+ return NXT_ERROR;
+ }
+
+ ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_PROCESS_CREATED,
+ -1, stream, my_port->id, NULL);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ nxt_alert(task, "%s failed to send CREATED message", process->name);
+ nxt_port_rpc_cancel(task, my_port, stream);
+ return NXT_ERROR;
+ }
+
+ nxt_debug(task, "%s created", process->name);
+
+ return NXT_OK;
+}
+
+
+static void
+nxt_process_created_ok(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data)
+{
+ nxt_int_t ret;
+ nxt_process_t *process;
+ nxt_process_init_t *init;
+
+ process = data;
+ init = nxt_process_init(process);
+
+ ret = nxt_process_apply_creds(task, process);
+ if (nxt_slow_path(ret != NXT_OK)) {
goto fail;
}
- return;
+ nxt_log(task, NXT_LOG_INFO, "%s started", process->name);
+
+ ret = init->start(task, &process->data);
fail:
- exit(1);
+ nxt_process_quit(task, ret == NXT_OK ? 0 : 1);
+}
+
+
+static void
+nxt_process_created_error(nxt_task_t *task, nxt_port_recv_msg_t *msg,
+ void *data)
+{
+ nxt_process_t *process;
+ nxt_process_init_t *init;
+
+ process = data;
+ init = nxt_process_init(process);
+
+ nxt_alert(task, "%s failed to start", init->name);
+
+ nxt_process_quit(task, 1);
+}
+
+
+nxt_int_t
+nxt_process_core_setup(nxt_task_t *task, nxt_process_t *process)
+{
+ nxt_int_t ret;
+
+ ret = nxt_process_apply_creds(task, process);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+
+ process->state = NXT_PROCESS_STATE_READY;
+
+ return NXT_OK;
+}
+
+
+#if (NXT_HAVE_CLONE_NEWUSER)
+
+nxt_int_t
+nxt_process_vldt_isolation_creds(nxt_task_t *task, nxt_process_t *process)
+{
+ nxt_int_t ret;
+ nxt_clone_t *clone;
+ nxt_credential_t *creds;
+
+ clone = &process->isolation.clone;
+ creds = process->user_cred;
+
+ if (clone->uidmap.size == 0 && clone->gidmap.size == 0) {
+ return NXT_OK;
+ }
+
+ if (!nxt_is_clone_flag_set(clone->flags, NEWUSER)) {
+ if (nxt_slow_path(clone->uidmap.size > 0)) {
+ nxt_log(task, NXT_LOG_ERR, "\"uidmap\" is set but "
+ "\"isolation.namespaces.credential\" is false or unset");
+
+ return NXT_ERROR;
+ }
+
+ if (nxt_slow_path(clone->gidmap.size > 0)) {
+ nxt_log(task, NXT_LOG_ERR, "\"gidmap\" is set but "
+ "\"isolation.namespaces.credential\" is false or unset");
+
+ return NXT_ERROR;
+ }
+
+ return NXT_OK;
+ }
+
+ ret = nxt_clone_vldt_credential_uidmap(task, &clone->uidmap, creds);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+
+ return nxt_clone_vldt_credential_gidmap(task, &clone->gidmap, creds);
+}
+
+#endif
+
+
+nxt_int_t
+nxt_process_creds_set(nxt_task_t *task, nxt_process_t *process, nxt_str_t *user,
+ nxt_str_t *group)
+{
+ char *str;
+
+ process->user_cred = nxt_mp_zalloc(process->mem_pool,
+ sizeof(nxt_credential_t));
+
+ if (nxt_slow_path(process->user_cred == NULL)) {
+ return NXT_ERROR;
+ }
+
+ str = nxt_mp_zalloc(process->mem_pool, user->length + 1);
+ if (nxt_slow_path(str == NULL)) {
+ return NXT_ERROR;
+ }
+
+ nxt_memcpy(str, user->start, user->length);
+ str[user->length] = '\0';
+
+ process->user_cred->user = str;
+
+ if (group->start != NULL) {
+ str = nxt_mp_zalloc(process->mem_pool, group->length + 1);
+ if (nxt_slow_path(str == NULL)) {
+ return NXT_ERROR;
+ }
+
+ nxt_memcpy(str, group->start, group->length);
+ str[group->length] = '\0';
+
+ } else {
+ str = NULL;
+ }
+
+ return nxt_credential_get(task, process->mem_pool, process->user_cred, str);
+}
+
+
+nxt_int_t
+nxt_process_apply_creds(nxt_task_t *task, nxt_process_t *process)
+{
+ nxt_int_t ret, cap_setid;
+ nxt_runtime_t *rt;
+
+ rt = task->thread->runtime;
+
+ cap_setid = rt->capabilities.setid;
+
+#if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER)
+ if (!cap_setid
+ && nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
+ cap_setid = 1;
+ }
+#endif
+
+ if (cap_setid) {
+ ret = nxt_credential_setgids(task, process->user_cred);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+
+ ret = nxt_credential_setuid(task, process->user_cred);
+ if (nxt_slow_path(ret != NXT_OK)) {
+ return NXT_ERROR;
+ }
+ }
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_process_send_ready(nxt_task_t *task, nxt_process_t *process)
+{
+ nxt_int_t ret;
+ nxt_port_t *main_port;
+ nxt_runtime_t *rt;
+
+ rt = task->thread->runtime;
+
+ main_port = rt->port_by_type[NXT_PROCESS_MAIN];
+
+ nxt_assert(main_port != NULL);
+
+ ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_PROCESS_READY,
+ -1, process->stream, 0, NULL);
+
+ if (nxt_slow_path(ret != NXT_OK)) {
+ nxt_alert(task, "%s failed to send READY message", process->name);
+ return NXT_ERROR;
+ }
+
+ nxt_debug(task, "%s sent ready", process->name);
+
+ return NXT_OK;
}
@@ -625,3 +792,50 @@ nxt_process_connected_port_find(nxt_process_t *process, nxt_port_t *port)
return res;
}
+
+
+void
+nxt_process_quit(nxt_task_t *task, nxt_uint_t exit_status)
+{
+ nxt_uint_t n;
+ nxt_queue_t *listen;
+ nxt_runtime_t *rt;
+ nxt_queue_link_t *link, *next;
+ nxt_listen_event_t *lev;
+ nxt_listen_socket_t *ls;
+
+ rt = task->thread->runtime;
+
+ nxt_debug(task, "close listen connections");
+
+ listen = &task->thread->engine->listen_connections;
+
+ for (link = nxt_queue_first(listen);
+ link != nxt_queue_tail(listen);
+ link = next)
+ {
+ next = nxt_queue_next(link);
+ lev = nxt_queue_link_data(link, nxt_listen_event_t, link);
+ nxt_queue_remove(link);
+
+ nxt_fd_event_close(task->thread->engine, &lev->socket);
+ }
+
+ if (rt->listen_sockets != NULL) {
+
+ ls = rt->listen_sockets->elts;
+ n = rt->listen_sockets->nelts;
+
+ while (n != 0) {
+ nxt_socket_close(task, ls->socket);
+ ls->socket = -1;
+
+ ls++;
+ n--;
+ }
+
+ rt->listen_sockets->nelts = 0;
+ }
+
+ nxt_runtime_quit(task, exit_status);
+}
diff --git a/src/nxt_process.h b/src/nxt_process.h
index 3f7155c8..45bab25e 100644
--- a/src/nxt_process.h
+++ b/src/nxt_process.h
@@ -8,68 +8,123 @@
#define _NXT_PROCESS_H_INCLUDED_
#if (NXT_HAVE_CLONE)
+#include <unistd.h>
#include <nxt_clone.h>
#endif
-typedef pid_t nxt_pid_t;
+#if (NXT_HAVE_CLONE)
+/*
+ * Old glibc wrapper for getpid(2) returns a cached pid invalidated only by
+ * fork(2) calls. As we use clone(2) for container, it returns the wrong pid.
+ */
+#define nxt_getpid() \
+ syscall(__NR_getpid)
+#else
+#define nxt_getpid() \
+ getpid()
+#endif
+typedef pid_t nxt_pid_t;
-typedef struct nxt_process_init_s nxt_process_init_t;
-typedef nxt_int_t (*nxt_process_start_t)(nxt_task_t *task, void *data);
-typedef nxt_int_t (*nxt_process_restart_t)(nxt_task_t *task, nxt_runtime_t *rt,
- nxt_process_init_t *init);
-struct nxt_process_init_s {
- nxt_mp_t *mem_pool;
- nxt_process_start_t start;
- const char *name;
- nxt_credential_t *user_cred;
+typedef struct nxt_common_app_conf_s nxt_common_app_conf_t;
- const nxt_port_handlers_t *port_handlers;
- const nxt_sig_event_t *signals;
- nxt_process_type_t type;
+typedef struct {
+ nxt_runtime_t *rt;
+} nxt_discovery_init_t;
- void *data;
- uint32_t stream;
- union {
-#if (NXT_HAVE_CLONE)
- nxt_clone_t clone;
+typedef struct {
+ nxt_str_t conf;
+#if (NXT_TLS)
+ nxt_array_t *certs;
#endif
- } isolation;
-};
+} nxt_controller_init_t;
+
+
+typedef union {
+ void *discovery;
+ nxt_controller_init_t controller;
+ void *router;
+ nxt_common_app_conf_t *app;
+} nxt_process_data_t;
+
+
+typedef enum {
+ NXT_PROCESS_STATE_CREATING = 0,
+ NXT_PROCESS_STATE_CREATED,
+ NXT_PROCESS_STATE_READY,
+} nxt_process_state_t;
typedef struct nxt_port_mmap_s nxt_port_mmap_t;
-typedef struct nxt_port_mmaps_s nxt_port_mmaps_t;
-struct nxt_port_mmaps_s {
+
+typedef struct {
nxt_thread_mutex_t mutex;
uint32_t size;
uint32_t cap;
nxt_port_mmap_t *elts;
-};
+} nxt_port_mmaps_t;
typedef struct {
- nxt_pid_t pid;
- nxt_queue_t ports; /* of nxt_port_t */
- nxt_bool_t ready;
- nxt_bool_t registered;
- nxt_int_t use_count;
+ nxt_pid_t pid;
+ const char *name;
+ nxt_queue_t ports; /* of nxt_port_t */
+ nxt_process_state_t state;
+ nxt_bool_t registered;
+ nxt_int_t use_count;
+
+ nxt_port_mmaps_t incoming;
+ nxt_port_mmaps_t outgoing;
+
+ nxt_thread_mutex_t cp_mutex;
+ nxt_lvlhsh_t connected_ports; /* of nxt_port_t */
- nxt_process_init_t *init;
+ uint32_t stream;
- nxt_port_mmaps_t incoming;
- nxt_port_mmaps_t outgoing;
+ nxt_mp_t *mem_pool;
+ nxt_credential_t *user_cred;
- nxt_thread_mutex_t cp_mutex;
- nxt_lvlhsh_t connected_ports; /* of nxt_port_t */
+ nxt_process_data_t data;
+
+ union {
+#if (NXT_HAVE_CLONE)
+ nxt_clone_t clone;
+#endif
+ } isolation;
} nxt_process_t;
+typedef nxt_int_t (*nxt_process_prefork_t)(nxt_task_t *task,
+ nxt_process_t *process, nxt_mp_t *mp);
+typedef nxt_int_t (*nxt_process_postfork_t)(nxt_task_t *task,
+ nxt_process_t *process, nxt_mp_t *mp);
+typedef nxt_int_t (*nxt_process_setup_t)(nxt_task_t *task,
+ nxt_process_t *process);
+typedef nxt_int_t (*nxt_process_start_t)(nxt_task_t *task,
+ nxt_process_data_t *data);
+
+
+typedef struct {
+ const char *name;
+ nxt_process_type_t type;
+
+ nxt_process_prefork_t prefork;
+
+ nxt_process_setup_t setup;
+ nxt_process_start_t start;
+
+ uint8_t restart; /* 1-bit */
+
+ const nxt_port_handlers_t *port_handlers;
+ const nxt_sig_event_t *signals;
+} nxt_process_init_t;
+
+
extern nxt_bool_t nxt_proc_conn_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX];
extern nxt_bool_t
nxt_proc_remove_notify_matrix[NXT_PROCESS_MAX][NXT_PROCESS_MAX];
@@ -84,6 +139,9 @@ NXT_EXPORT void nxt_nanosleep(nxt_nsec_t ns);
NXT_EXPORT void nxt_process_arguments(nxt_task_t *task, char **orig_argv,
char ***orig_envp);
+#define nxt_process_init(process) \
+ (nxt_pointer_to(process, sizeof(nxt_process_t)))
+
#define nxt_process_port_remove(port) \
nxt_queue_remove(&port->link)
@@ -113,11 +171,18 @@ void nxt_process_connected_port_remove(nxt_process_t *process,
nxt_port_t *nxt_process_connected_port_find(nxt_process_t *process,
nxt_port_t *port);
-void nxt_worker_process_quit_handler(nxt_task_t *task,
- nxt_port_recv_msg_t *msg);
+void nxt_process_quit(nxt_task_t *task, nxt_uint_t exit_status);
+void nxt_signal_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg);
-void nxt_init_destroy(nxt_runtime_t *rt, nxt_process_init_t *init);
+nxt_int_t nxt_process_core_setup(nxt_task_t *task, nxt_process_t *process);
+nxt_int_t nxt_process_creds_set(nxt_task_t *task, nxt_process_t *process,
+ nxt_str_t *user, nxt_str_t *group);
+nxt_int_t nxt_process_apply_creds(nxt_task_t *task, nxt_process_t *process);
+#if (NXT_HAVE_CLONE_NEWUSER)
+nxt_int_t nxt_process_vldt_isolation_creds(nxt_task_t *task,
+ nxt_process_t *process);
+#endif
#if (NXT_HAVE_SETPROCTITLE)
diff --git a/src/nxt_process_type.h b/src/nxt_process_type.h
index 5ff06d63..14deda19 100644
--- a/src/nxt_process_type.h
+++ b/src/nxt_process_type.h
@@ -13,7 +13,7 @@ typedef enum {
NXT_PROCESS_DISCOVERY,
NXT_PROCESS_CONTROLLER,
NXT_PROCESS_ROUTER,
- NXT_PROCESS_WORKER,
+ NXT_PROCESS_APP,
NXT_PROCESS_MAX,
} nxt_process_type_t;
diff --git a/src/nxt_python_wsgi.c b/src/nxt_python_wsgi.c
index 14211f3f..089d15c0 100644
--- a/src/nxt_python_wsgi.c
+++ b/src/nxt_python_wsgi.c
@@ -65,7 +65,8 @@ typedef struct {
PyObject_HEAD
} nxt_py_error_t;
-static nxt_int_t nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
+static nxt_int_t nxt_python_start(nxt_task_t *task,
+ nxt_process_data_t *data);
static nxt_int_t nxt_python_init_strings(void);
static void nxt_python_request_handler(nxt_unit_request_info_t *req);
static void nxt_python_atexit(void);
@@ -116,7 +117,7 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
nxt_string("python"),
PY_VERSION,
NULL,
- nxt_python_init,
+ nxt_python_start,
};
@@ -211,7 +212,7 @@ static nxt_python_string_t nxt_python_strings[] = {
static nxt_int_t
-nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
+nxt_python_start(nxt_task_t *task, nxt_process_data_t *data)
{
int rc;
char *nxt_py_module;
@@ -219,6 +220,7 @@ nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
PyObject *obj, *pypath, *module;
nxt_unit_ctx_t *unit_ctx;
nxt_unit_init_t python_init;
+ nxt_common_app_conf_t *app_conf;
nxt_python_app_conf_t *c;
#if PY_MAJOR_VERSION == 3
char *path;
@@ -229,7 +231,8 @@ nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
static const char bin_python[] = "/bin/python";
#endif
- c = &conf->u.python;
+ app_conf = data->app;
+ c = &app_conf->u.python;
if (c->module.length == 0) {
nxt_alert(task, "python module is empty");
@@ -410,7 +413,7 @@ nxt_python_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
nxt_unit_default_init(task, &python_init);
python_init.callbacks.request_handler = nxt_python_request_handler;
- python_init.shm_limit = conf->shm_limit;
+ python_init.shm_limit = data->app->shm_limit;
unit_ctx = nxt_unit_init(&python_init);
if (nxt_slow_path(unit_ctx == NULL)) {
diff --git a/src/nxt_router.c b/src/nxt_router.c
index b4cba08b..788199c7 100644
--- a/src/nxt_router.c
+++ b/src/nxt_router.c
@@ -75,6 +75,9 @@ struct nxt_port_select_state_s {
typedef struct nxt_port_select_state_s nxt_port_select_state_t;
+static nxt_int_t nxt_router_prefork(nxt_task_t *task, nxt_process_t *process,
+ nxt_mp_t *mp);
+static nxt_int_t nxt_router_start(nxt_task_t *task, nxt_process_data_t *data);
static void nxt_router_greet_controller(nxt_task_t *task,
nxt_port_t *controller_port);
@@ -268,8 +271,8 @@ static const nxt_str_t *nxt_app_msg_prefix[] = {
};
-nxt_port_handlers_t nxt_router_process_port_handlers = {
- .quit = nxt_worker_process_quit_handler,
+static const nxt_port_handlers_t nxt_router_process_port_handlers = {
+ .quit = nxt_signal_quit_handler,
.new_port = nxt_router_new_port_handler,
.change_file = nxt_port_change_log_file_handler,
.mmap = nxt_port_mmap_handler,
@@ -282,8 +285,29 @@ nxt_port_handlers_t nxt_router_process_port_handlers = {
};
-nxt_int_t
-nxt_router_start(nxt_task_t *task, void *data)
+const nxt_process_init_t nxt_router_process = {
+ .name = "router",
+ .type = NXT_PROCESS_ROUTER,
+ .prefork = nxt_router_prefork,
+ .restart = 1,
+ .setup = nxt_process_core_setup,
+ .start = nxt_router_start,
+ .port_handlers = &nxt_router_process_port_handlers,
+ .signals = nxt_process_signals,
+};
+
+
+static nxt_int_t
+nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
+{
+ nxt_runtime_stop_app_processes(task, task->thread->runtime);
+
+ return NXT_OK;
+}
+
+
+static nxt_int_t
+nxt_router_start(nxt_task_t *task, nxt_process_data_t *data)
{
nxt_int_t ret;
nxt_port_t *controller_port;
@@ -292,6 +316,8 @@ nxt_router_start(nxt_task_t *task, void *data)
rt = task->thread->runtime;
+ nxt_log(task, NXT_LOG_INFO, "router started");
+
#if (NXT_TLS)
rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL");
if (nxt_slow_path(rt->tls == NULL)) {
@@ -382,8 +408,8 @@ nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port,
goto failed;
}
- ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_WORKER, -1,
- stream, port->id, b);
+ ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_PROCESS,
+ -1, stream, port->id, b);
if (nxt_slow_path(ret != NXT_OK)) {
nxt_port_rpc_cancel(task, port, stream);
@@ -862,7 +888,7 @@ nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
}
if (msg->u.new_port == NULL
- || msg->u.new_port->type != NXT_PROCESS_WORKER)
+ || msg->u.new_port->type != NXT_PROCESS_APP)
{
msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
}
@@ -2400,8 +2426,8 @@ nxt_router_app_rpc_create(nxt_task_t *task,
goto fail;
}
- ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_WORKER, -1,
- stream, router_port->id, b);
+ ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_PROCESS,
+ -1, stream, router_port->id, b);
if (nxt_slow_path(ret != NXT_OK)) {
nxt_port_rpc_cancel(task, router_port, stream);
diff --git a/src/nxt_runtime.c b/src/nxt_runtime.c
index ea01f06f..d7e35dec 100644
--- a/src/nxt_runtime.c
+++ b/src/nxt_runtime.c
@@ -21,6 +21,7 @@ static nxt_int_t nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt);
static void nxt_runtime_start(nxt_task_t *task, void *obj, void *data);
static void nxt_runtime_initial_start(nxt_task_t *task, nxt_uint_t status);
static void nxt_runtime_close_idle_connections(nxt_event_engine_t *engine);
+static void nxt_runtime_stop_all_processes(nxt_task_t *task, nxt_runtime_t *rt);
static void nxt_runtime_exit(nxt_task_t *task, void *obj, void *data);
static nxt_int_t nxt_runtime_event_engine_change(nxt_task_t *task,
nxt_runtime_t *rt);
@@ -438,7 +439,7 @@ nxt_runtime_quit(nxt_task_t *task, nxt_uint_t status)
}
if (rt->type == NXT_PROCESS_MAIN) {
- nxt_main_stop_all_processes(task, rt);
+ nxt_runtime_stop_all_processes(task, rt);
done = 0;
}
}
@@ -478,6 +479,50 @@ nxt_runtime_close_idle_connections(nxt_event_engine_t *engine)
}
+void
+nxt_runtime_stop_app_processes(nxt_task_t *task, nxt_runtime_t *rt)
+{
+ nxt_port_t *port;
+ nxt_process_t *process;
+ nxt_process_init_t *init;
+
+ nxt_runtime_process_each(rt, process) {
+
+ init = nxt_process_init(process);
+
+ if (init->type == NXT_PROCESS_APP) {
+
+ nxt_process_port_each(process, port) {
+
+ (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1,
+ 0, 0, NULL);
+
+ } nxt_process_port_loop;
+ }
+
+ } nxt_runtime_process_loop;
+}
+
+
+static void
+nxt_runtime_stop_all_processes(nxt_task_t *task, nxt_runtime_t *rt)
+{
+ nxt_port_t *port;
+ nxt_process_t *process;
+
+ nxt_runtime_process_each(rt, process) {
+
+ nxt_process_port_each(process, port) {
+
+ (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0,
+ 0, NULL);
+
+ } nxt_process_port_loop;
+
+ } nxt_runtime_process_loop;
+}
+
+
static void
nxt_runtime_exit(nxt_task_t *task, void *obj, void *data)
{
@@ -525,6 +570,10 @@ nxt_runtime_exit(nxt_task_t *task, void *obj, void *data)
} nxt_runtime_process_loop;
+ if (rt->port_by_type[rt->type] != NULL) {
+ nxt_port_use(task, rt->port_by_type[rt->type], -1);
+ }
+
nxt_thread_mutex_destroy(&rt->processes_mutex);
status = rt->status;
@@ -1306,7 +1355,9 @@ nxt_runtime_process_new(nxt_runtime_t *rt)
/* TODO: memory failures. */
- process = nxt_mp_zalloc(rt->mem_pool, sizeof(nxt_process_t));
+ process = nxt_mp_zalloc(rt->mem_pool,
+ sizeof(nxt_process_t) + sizeof(nxt_process_init_t));
+
if (nxt_slow_path(process == NULL)) {
return NULL;
}
@@ -1347,8 +1398,9 @@ nxt_runtime_process_release(nxt_runtime_t *rt, nxt_process_t *process)
nxt_thread_mutex_destroy(&process->outgoing.mutex);
nxt_thread_mutex_destroy(&process->cp_mutex);
- if (process->init != NULL) {
- nxt_mp_destroy(process->init->mem_pool);
+ /* processes from nxt_runtime_process_get() have no memory pool */
+ if (process->mem_pool != NULL) {
+ nxt_mp_destroy(process->mem_pool);
}
nxt_mp_free(rt->mem_pool, process);
diff --git a/src/nxt_runtime.h b/src/nxt_runtime.h
index a364c38c..d29b6b4d 100644
--- a/src/nxt_runtime.h
+++ b/src/nxt_runtime.h
@@ -110,6 +110,7 @@ nxt_port_t *nxt_runtime_process_port_create(nxt_task_t *task, nxt_runtime_t *rt,
nxt_pid_t pid, nxt_port_id_t id, nxt_process_type_t type);
void nxt_runtime_port_remove(nxt_task_t *task, nxt_port_t *port);
+void nxt_runtime_stop_app_processes(nxt_task_t *task, nxt_runtime_t *rt);
NXT_EXPORT nxt_port_t *nxt_runtime_port_find(nxt_runtime_t *rt, nxt_pid_t pid,
nxt_port_id_t port_id);
diff --git a/src/nxt_signal_handlers.c b/src/nxt_signal_handlers.c
new file mode 100644
index 00000000..69ae2bc4
--- /dev/null
+++ b/src/nxt_signal_handlers.c
@@ -0,0 +1,67 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ * Copyright (C) NGINX, Inc.
+ */
+
+#include <nxt_main.h>
+#include <nxt_runtime.h>
+#include <nxt_port.h>
+#include <nxt_main_process.h>
+#include <nxt_router.h>
+
+
+static void nxt_signal_handler(nxt_task_t *task, void *obj, void *data);
+static void nxt_signal_sigterm_handler(nxt_task_t *task, void *obj, void *data);
+static void nxt_signal_sigquit_handler(nxt_task_t *task, void *obj, void *data);
+
+
+const nxt_sig_event_t nxt_process_signals[] = {
+ nxt_event_signal(SIGHUP, nxt_signal_handler),
+ nxt_event_signal(SIGINT, nxt_signal_sigterm_handler),
+ nxt_event_signal(SIGQUIT, nxt_signal_sigquit_handler),
+ nxt_event_signal(SIGTERM, nxt_signal_sigterm_handler),
+ nxt_event_signal(SIGCHLD, nxt_signal_handler),
+ nxt_event_signal(SIGUSR1, nxt_signal_handler),
+ nxt_event_signal(SIGUSR2, nxt_signal_handler),
+ nxt_event_signal_end,
+};
+
+
+static void
+nxt_signal_handler(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_trace(task, "signal signo:%d (%s) recevied, ignored",
+ (int) (uintptr_t) obj, data);
+}
+
+
+void
+nxt_signal_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
+{
+ nxt_process_quit(task, 0);
+}
+
+
+static void
+nxt_signal_sigterm_handler(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_debug(task, "sigterm handler signo:%d (%s)",
+ (int) (uintptr_t) obj, data);
+
+ /* A fast exit. */
+
+ nxt_runtime_quit(task, 0);
+}
+
+
+static void
+nxt_signal_sigquit_handler(nxt_task_t *task, void *obj, void *data)
+{
+ nxt_debug(task, "sigquit handler signo:%d (%s)",
+ (int) (uintptr_t) obj, data);
+
+ /* A graceful exit. */
+
+ nxt_process_quit(task, 0);
+}
diff --git a/src/nxt_unit.c b/src/nxt_unit.c
index 67244420..9f6eab95 100644
--- a/src/nxt_unit.c
+++ b/src/nxt_unit.c
@@ -4248,7 +4248,7 @@ nxt_unit_send_port(nxt_unit_ctx_t *ctx, nxt_unit_port_id_t *dst,
m.new_port.id = new_port->id;
m.new_port.pid = new_port->pid;
- m.new_port.type = NXT_PROCESS_WORKER;
+ m.new_port.type = NXT_PROCESS_APP;
m.new_port.max_size = 16 * 1024;
m.new_port.max_share = 64 * 1024;
diff --git a/src/nxt_worker_process.c b/src/nxt_worker_process.c
deleted file mode 100644
index 754e2ea8..00000000
--- a/src/nxt_worker_process.c
+++ /dev/null
@@ -1,118 +0,0 @@
-
-/*
- * Copyright (C) Igor Sysoev
- * Copyright (C) NGINX, Inc.
- */
-
-#include <nxt_main.h>
-#include <nxt_runtime.h>
-#include <nxt_port.h>
-#include <nxt_main_process.h>
-#include <nxt_router.h>
-
-
-static void nxt_worker_process_quit(nxt_task_t *task);
-static void nxt_worker_process_signal_handler(nxt_task_t *task, void *obj,
- void *data);
-static void nxt_worker_process_sigterm_handler(nxt_task_t *task, void *obj,
- void *data);
-static void nxt_worker_process_sigquit_handler(nxt_task_t *task, void *obj,
- void *data);
-
-
-const nxt_sig_event_t nxt_worker_process_signals[] = {
- nxt_event_signal(SIGHUP, nxt_worker_process_signal_handler),
- nxt_event_signal(SIGINT, nxt_worker_process_sigterm_handler),
- nxt_event_signal(SIGQUIT, nxt_worker_process_sigquit_handler),
- nxt_event_signal(SIGTERM, nxt_worker_process_sigterm_handler),
- nxt_event_signal(SIGCHLD, nxt_worker_process_signal_handler),
- nxt_event_signal(SIGUSR1, nxt_worker_process_signal_handler),
- nxt_event_signal(SIGUSR2, nxt_worker_process_signal_handler),
- nxt_event_signal_end,
-};
-
-
-static void
-nxt_worker_process_quit(nxt_task_t *task)
-{
- nxt_uint_t n;
- nxt_queue_t *listen;
- nxt_runtime_t *rt;
- nxt_queue_link_t *link, *next;
- nxt_listen_event_t *lev;
- nxt_listen_socket_t *ls;
-
- rt = task->thread->runtime;
-
- nxt_debug(task, "close listen connections");
-
- listen = &task->thread->engine->listen_connections;
-
- for (link = nxt_queue_first(listen);
- link != nxt_queue_tail(listen);
- link = next)
- {
- next = nxt_queue_next(link);
- lev = nxt_queue_link_data(link, nxt_listen_event_t, link);
- nxt_queue_remove(link);
-
- nxt_fd_event_close(task->thread->engine, &lev->socket);
- }
-
- if (rt->listen_sockets != NULL) {
-
- ls = rt->listen_sockets->elts;
- n = rt->listen_sockets->nelts;
-
- while (n != 0) {
- nxt_socket_close(task, ls->socket);
- ls->socket = -1;
-
- ls++;
- n--;
- }
-
- rt->listen_sockets->nelts = 0;
- }
-
- nxt_runtime_quit(task, 0);
-}
-
-
-static void
-nxt_worker_process_signal_handler(nxt_task_t *task, void *obj, void *data)
-{
- nxt_trace(task, "signal signo:%d (%s) recevied, ignored",
- (int) (uintptr_t) obj, data);
-}
-
-
-void
-nxt_worker_process_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
-{
- nxt_worker_process_quit(task);
-}
-
-
-static void
-nxt_worker_process_sigterm_handler(nxt_task_t *task, void *obj, void *data)
-{
- nxt_debug(task, "sigterm handler signo:%d (%s)",
- (int) (uintptr_t) obj, data);
-
- /* A fast exit. */
-
- nxt_runtime_quit(task, 0);
-}
-
-
-static void
-nxt_worker_process_sigquit_handler(nxt_task_t *task, void *obj, void *data)
-{
- nxt_debug(task, "sigquit handler signo:%d (%s)",
- (int) (uintptr_t) obj, data);
-
- /* A graceful exit. */
-
- nxt_worker_process_quit(task);
-}
diff --git a/src/perl/nxt_perl_psgi.c b/src/perl/nxt_perl_psgi.c
index 548e6daa..5e9200dc 100644
--- a/src/perl/nxt_perl_psgi.c
+++ b/src/perl/nxt_perl_psgi.c
@@ -95,8 +95,8 @@ static int nxt_perl_psgi_result_array(PerlInterpreter *my_perl,
static void nxt_perl_psgi_result_cb(PerlInterpreter *my_perl, SV *result,
nxt_unit_request_info_t *req);
-static nxt_int_t nxt_perl_psgi_init(nxt_task_t *task,
- nxt_common_app_conf_t *conf);
+static nxt_int_t nxt_perl_psgi_start(nxt_task_t *task,
+ nxt_process_data_t *conf);
static void nxt_perl_psgi_request_handler(nxt_unit_request_info_t *req);
static void nxt_perl_psgi_atexit(void);
@@ -119,7 +119,7 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
nxt_string("perl"),
PERL_VERSION_STRING,
NULL,
- nxt_perl_psgi_init,
+ nxt_perl_psgi_start,
};
@@ -1134,14 +1134,17 @@ nxt_perl_psgi_result_cb(PerlInterpreter *my_perl, SV *result,
static nxt_int_t
-nxt_perl_psgi_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
+nxt_perl_psgi_start(nxt_task_t *task, nxt_process_data_t *data)
{
int rc;
nxt_unit_ctx_t *unit_ctx;
nxt_unit_init_t perl_init;
PerlInterpreter *my_perl;
+ nxt_common_app_conf_t *conf;
nxt_perl_psgi_module_t module;
+ conf = data->app;
+
my_perl = nxt_perl_psgi_interpreter_init(task, conf->u.perl.script,
&module.app);
diff --git a/src/ruby/nxt_ruby.c b/src/ruby/nxt_ruby.c
index 417e2d8d..40f72f51 100644
--- a/src/ruby/nxt_ruby.c
+++ b/src/ruby/nxt_ruby.c
@@ -28,7 +28,8 @@ typedef struct {
} nxt_ruby_rack_init_t;
-static nxt_int_t nxt_ruby_init(nxt_task_t *task, nxt_common_app_conf_t *conf);
+static nxt_int_t nxt_ruby_start(nxt_task_t *task,
+ nxt_process_data_t *data);
static VALUE nxt_ruby_init_basic(VALUE arg);
static nxt_int_t nxt_ruby_init_io(nxt_task_t *task);
static VALUE nxt_ruby_rack_init(nxt_ruby_rack_init_t *rack_init);
@@ -78,21 +79,24 @@ NXT_EXPORT nxt_app_module_t nxt_app_module = {
nxt_string("ruby"),
ruby_version,
NULL,
- nxt_ruby_init,
+ nxt_ruby_start,
};
static nxt_int_t
-nxt_ruby_init(nxt_task_t *task, nxt_common_app_conf_t *conf)
+nxt_ruby_start(nxt_task_t *task, nxt_process_data_t *data)
{
- int state, rc;
- VALUE res;
- nxt_unit_ctx_t *unit_ctx;
- nxt_unit_init_t ruby_unit_init;
- nxt_ruby_rack_init_t rack_init;
+ int state, rc;
+ VALUE res;
+ nxt_unit_ctx_t *unit_ctx;
+ nxt_unit_init_t ruby_unit_init;
+ nxt_ruby_rack_init_t rack_init;
+ nxt_common_app_conf_t *conf;
static char *argv[2] = { (char *) "NGINX_Unit", (char *) "-e0" };
+ conf = data->app;
+
RUBY_INIT_STACK
ruby_init();
ruby_options(2, argv);