xref: /unit/src/nxt_runtime.c (revision 1998:c8790d2a89bb)
120Sigor@sysoev.ru 
220Sigor@sysoev.ru /*
320Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
420Sigor@sysoev.ru  * Copyright (C) Valentin V. Bartenev
520Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
620Sigor@sysoev.ru  */
720Sigor@sysoev.ru 
820Sigor@sysoev.ru #include <nxt_main.h>
920Sigor@sysoev.ru #include <nxt_runtime.h>
1020Sigor@sysoev.ru #include <nxt_port.h>
11240Sigor@sysoev.ru #include <nxt_main_process.h>
12141Smax.romanov@nginx.com #include <nxt_router.h>
131721Saxel.duch@nginx.com #include <nxt_regex.h>
1420Sigor@sysoev.ru 
1520Sigor@sysoev.ru 
1620Sigor@sysoev.ru static nxt_int_t nxt_runtime_inherited_listen_sockets(nxt_task_t *task,
1720Sigor@sysoev.ru     nxt_runtime_t *rt);
1820Sigor@sysoev.ru static nxt_int_t nxt_runtime_systemd_listen_sockets(nxt_task_t *task,
1920Sigor@sysoev.ru     nxt_runtime_t *rt);
2020Sigor@sysoev.ru static nxt_int_t nxt_runtime_event_engines(nxt_task_t *task, nxt_runtime_t *rt);
2120Sigor@sysoev.ru static nxt_int_t nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt);
2220Sigor@sysoev.ru static void nxt_runtime_start(nxt_task_t *task, void *obj, void *data);
23697Sigor@sysoev.ru static void nxt_runtime_initial_start(nxt_task_t *task, nxt_uint_t status);
2420Sigor@sysoev.ru static void nxt_runtime_close_idle_connections(nxt_event_engine_t *engine);
251488St.nateldemoura@f5.com static void nxt_runtime_stop_all_processes(nxt_task_t *task, nxt_runtime_t *rt);
2620Sigor@sysoev.ru static void nxt_runtime_exit(nxt_task_t *task, void *obj, void *data);
2720Sigor@sysoev.ru static nxt_int_t nxt_runtime_event_engine_change(nxt_task_t *task,
2820Sigor@sysoev.ru     nxt_runtime_t *rt);
2920Sigor@sysoev.ru static nxt_int_t nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt);
3020Sigor@sysoev.ru static nxt_int_t nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt);
3120Sigor@sysoev.ru static nxt_int_t nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt);
3220Sigor@sysoev.ru static nxt_int_t nxt_runtime_log_files_init(nxt_runtime_t *rt);
3320Sigor@sysoev.ru static nxt_int_t nxt_runtime_log_files_create(nxt_task_t *task,
3420Sigor@sysoev.ru     nxt_runtime_t *rt);
3520Sigor@sysoev.ru static nxt_int_t nxt_runtime_pid_file_create(nxt_task_t *task,
3620Sigor@sysoev.ru     nxt_file_name_t *pid_file);
3720Sigor@sysoev.ru static void nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt,
3820Sigor@sysoev.ru     nxt_runtime_cont_t cont);
39223Sigor@sysoev.ru static void nxt_runtime_thread_pool_init(void);
40223Sigor@sysoev.ru static void nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj,
41223Sigor@sysoev.ru     void *data);
421254Shongzhidao@gmail.com static nxt_process_t *nxt_runtime_process_get(nxt_runtime_t *rt, nxt_pid_t pid);
431254Shongzhidao@gmail.com static void nxt_runtime_port_add(nxt_task_t *task, nxt_port_t *port);
44196Smax.romanov@nginx.com 
4520Sigor@sysoev.ru 
4620Sigor@sysoev.ru nxt_int_t
nxt_runtime_create(nxt_task_t * task)4720Sigor@sysoev.ru nxt_runtime_create(nxt_task_t *task)
4820Sigor@sysoev.ru {
49216Sigor@sysoev.ru     nxt_mp_t               *mp;
50216Sigor@sysoev.ru     nxt_int_t              ret;
51216Sigor@sysoev.ru     nxt_array_t            *listen_sockets;
52216Sigor@sysoev.ru     nxt_runtime_t          *rt;
53216Sigor@sysoev.ru     nxt_app_lang_module_t  *lang;
5420Sigor@sysoev.ru 
5565Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
5620Sigor@sysoev.ru     if (nxt_slow_path(mp == NULL)) {
5720Sigor@sysoev.ru         return NXT_ERROR;
5820Sigor@sysoev.ru     }
5920Sigor@sysoev.ru 
6065Sigor@sysoev.ru     rt = nxt_mp_zget(mp, sizeof(nxt_runtime_t));
6165Sigor@sysoev.ru     if (nxt_slow_path(rt == NULL)) {
621013Smax.romanov@nginx.com         goto fail;
6365Sigor@sysoev.ru     }
6420Sigor@sysoev.ru 
6520Sigor@sysoev.ru     task->thread->runtime = rt;
6620Sigor@sysoev.ru     rt->mem_pool = mp;
6720Sigor@sysoev.ru 
68196Smax.romanov@nginx.com     nxt_thread_mutex_create(&rt->processes_mutex);
69196Smax.romanov@nginx.com 
7020Sigor@sysoev.ru     rt->services = nxt_services_init(mp);
7120Sigor@sysoev.ru     if (nxt_slow_path(rt->services == NULL)) {
7220Sigor@sysoev.ru         goto fail;
7320Sigor@sysoev.ru     }
7420Sigor@sysoev.ru 
75216Sigor@sysoev.ru     rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t));
76216Sigor@sysoev.ru     if (nxt_slow_path(rt->languages == NULL)) {
77216Sigor@sysoev.ru         goto fail;
78216Sigor@sysoev.ru     }
79216Sigor@sysoev.ru 
80216Sigor@sysoev.ru     /* Should not fail. */
81216Sigor@sysoev.ru     lang = nxt_array_add(rt->languages);
82804Svbart@nginx.com     lang->type = NXT_APP_EXTERNAL;
83354Svbart@nginx.com     lang->version = (u_char *) "";
84216Sigor@sysoev.ru     lang->file = NULL;
85804Svbart@nginx.com     lang->module = &nxt_external_module;
861580St.nateldemoura@f5.com 
871580St.nateldemoura@f5.com     lang->mounts = nxt_array_create(mp, 1, sizeof(nxt_fs_mount_t));
881580St.nateldemoura@f5.com     if (nxt_slow_path(lang->mounts == NULL)) {
891580St.nateldemoura@f5.com         goto fail;
901580St.nateldemoura@f5.com     }
91216Sigor@sysoev.ru 
9220Sigor@sysoev.ru     listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t));
9320Sigor@sysoev.ru     if (nxt_slow_path(listen_sockets == NULL)) {
9420Sigor@sysoev.ru         goto fail;
9520Sigor@sysoev.ru     }
9620Sigor@sysoev.ru 
9720Sigor@sysoev.ru     rt->listen_sockets = listen_sockets;
9820Sigor@sysoev.ru 
9920Sigor@sysoev.ru     ret = nxt_runtime_inherited_listen_sockets(task, rt);
10020Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
10120Sigor@sysoev.ru         goto fail;
10220Sigor@sysoev.ru     }
10320Sigor@sysoev.ru 
10420Sigor@sysoev.ru     if (nxt_runtime_hostname(task, rt) != NXT_OK) {
10520Sigor@sysoev.ru         goto fail;
10620Sigor@sysoev.ru     }
10720Sigor@sysoev.ru 
10820Sigor@sysoev.ru     if (nxt_slow_path(nxt_runtime_log_files_init(rt) != NXT_OK)) {
10920Sigor@sysoev.ru         goto fail;
11020Sigor@sysoev.ru     }
11120Sigor@sysoev.ru 
11220Sigor@sysoev.ru     if (nxt_runtime_event_engines(task, rt) != NXT_OK) {
11320Sigor@sysoev.ru         goto fail;
11420Sigor@sysoev.ru     }
11520Sigor@sysoev.ru 
11620Sigor@sysoev.ru     if (nxt_slow_path(nxt_runtime_thread_pools(task->thread, rt) != NXT_OK)) {
11720Sigor@sysoev.ru         goto fail;
11820Sigor@sysoev.ru     }
11920Sigor@sysoev.ru 
12020Sigor@sysoev.ru     rt->start = nxt_runtime_initial_start;
12120Sigor@sysoev.ru 
122221Sigor@sysoev.ru     if (nxt_runtime_conf_init(task, rt) != NXT_OK) {
123221Sigor@sysoev.ru         goto fail;
124221Sigor@sysoev.ru     }
125221Sigor@sysoev.ru 
1261487Smax.romanov@nginx.com     if (nxt_port_rpc_init() != NXT_OK) {
1271487Smax.romanov@nginx.com         goto fail;
1281487Smax.romanov@nginx.com     }
1291487Smax.romanov@nginx.com 
1301563Svbart@nginx.com     if (nxt_slow_path(nxt_http_register_variables() != NXT_OK)) {
1311563Svbart@nginx.com         goto fail;
1321563Svbart@nginx.com     }
1331563Svbart@nginx.com 
1341563Svbart@nginx.com     if (nxt_slow_path(nxt_var_index_init() != NXT_OK)) {
1351563Svbart@nginx.com         goto fail;
1361563Svbart@nginx.com     }
1371563Svbart@nginx.com 
13820Sigor@sysoev.ru     nxt_work_queue_add(&task->thread->engine->fast_work_queue,
13920Sigor@sysoev.ru                        nxt_runtime_start, task, rt, NULL);
14020Sigor@sysoev.ru 
14120Sigor@sysoev.ru     return NXT_OK;
14220Sigor@sysoev.ru 
14320Sigor@sysoev.ru fail:
14420Sigor@sysoev.ru 
14565Sigor@sysoev.ru     nxt_mp_destroy(mp);
14620Sigor@sysoev.ru 
14720Sigor@sysoev.ru     return NXT_ERROR;
14820Sigor@sysoev.ru }
14920Sigor@sysoev.ru 
15020Sigor@sysoev.ru 
15120Sigor@sysoev.ru static nxt_int_t
nxt_runtime_inherited_listen_sockets(nxt_task_t * task,nxt_runtime_t * rt)15220Sigor@sysoev.ru nxt_runtime_inherited_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt)
15320Sigor@sysoev.ru {
15420Sigor@sysoev.ru     u_char               *v, *p;
15520Sigor@sysoev.ru     nxt_int_t            type;
15620Sigor@sysoev.ru     nxt_array_t          *inherited_sockets;
15720Sigor@sysoev.ru     nxt_socket_t         s;
15820Sigor@sysoev.ru     nxt_listen_socket_t  *ls;
15920Sigor@sysoev.ru 
16020Sigor@sysoev.ru     v = (u_char *) getenv("NGINX");
16120Sigor@sysoev.ru 
16220Sigor@sysoev.ru     if (v == NULL) {
16320Sigor@sysoev.ru         return nxt_runtime_systemd_listen_sockets(task, rt);
16420Sigor@sysoev.ru     }
16520Sigor@sysoev.ru 
166564Svbart@nginx.com     nxt_alert(task, "using inherited listen sockets: %s", v);
16720Sigor@sysoev.ru 
16820Sigor@sysoev.ru     inherited_sockets = nxt_array_create(rt->mem_pool,
16920Sigor@sysoev.ru                                          1, sizeof(nxt_listen_socket_t));
17020Sigor@sysoev.ru     if (inherited_sockets == NULL) {
17120Sigor@sysoev.ru         return NXT_ERROR;
17220Sigor@sysoev.ru     }
17320Sigor@sysoev.ru 
17420Sigor@sysoev.ru     rt->inherited_sockets = inherited_sockets;
17520Sigor@sysoev.ru 
17620Sigor@sysoev.ru     for (p = v; *p != '\0'; p++) {
17720Sigor@sysoev.ru 
17820Sigor@sysoev.ru         if (*p == ';') {
17920Sigor@sysoev.ru             s = nxt_int_parse(v, p - v);
18020Sigor@sysoev.ru 
18120Sigor@sysoev.ru             if (nxt_slow_path(s < 0)) {
182564Svbart@nginx.com                 nxt_alert(task, "invalid socket number \"%s\" "
183564Svbart@nginx.com                           "in NGINX environment variable, "
184564Svbart@nginx.com                           "ignoring the rest of the variable", v);
18520Sigor@sysoev.ru                 return NXT_ERROR;
18620Sigor@sysoev.ru             }
18720Sigor@sysoev.ru 
18820Sigor@sysoev.ru             v = p + 1;
18920Sigor@sysoev.ru 
19020Sigor@sysoev.ru             ls = nxt_array_zero_add(inherited_sockets);
19120Sigor@sysoev.ru             if (nxt_slow_path(ls == NULL)) {
19220Sigor@sysoev.ru                 return NXT_ERROR;
19320Sigor@sysoev.ru             }
19420Sigor@sysoev.ru 
19520Sigor@sysoev.ru             ls->socket = s;
19620Sigor@sysoev.ru 
19720Sigor@sysoev.ru             ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s);
19820Sigor@sysoev.ru             if (nxt_slow_path(ls->sockaddr == NULL)) {
19920Sigor@sysoev.ru                 return NXT_ERROR;
20020Sigor@sysoev.ru             }
20120Sigor@sysoev.ru 
20220Sigor@sysoev.ru             type = nxt_socket_getsockopt(task, s, SOL_SOCKET, SO_TYPE);
20320Sigor@sysoev.ru             if (nxt_slow_path(type == -1)) {
20420Sigor@sysoev.ru                 return NXT_ERROR;
20520Sigor@sysoev.ru             }
20620Sigor@sysoev.ru 
20720Sigor@sysoev.ru             ls->sockaddr->type = (uint16_t) type;
20820Sigor@sysoev.ru         }
20920Sigor@sysoev.ru     }
21020Sigor@sysoev.ru 
21120Sigor@sysoev.ru     return NXT_OK;
21220Sigor@sysoev.ru }
21320Sigor@sysoev.ru 
21420Sigor@sysoev.ru 
21520Sigor@sysoev.ru static nxt_int_t
nxt_runtime_systemd_listen_sockets(nxt_task_t * task,nxt_runtime_t * rt)21620Sigor@sysoev.ru nxt_runtime_systemd_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt)
21720Sigor@sysoev.ru {
21820Sigor@sysoev.ru     u_char               *nfd, *pid;
21920Sigor@sysoev.ru     nxt_int_t            n;
22020Sigor@sysoev.ru     nxt_array_t          *inherited_sockets;
22120Sigor@sysoev.ru     nxt_socket_t         s;
22220Sigor@sysoev.ru     nxt_listen_socket_t  *ls;
22320Sigor@sysoev.ru 
22420Sigor@sysoev.ru     /*
22520Sigor@sysoev.ru      * Number of listening sockets passed.  The socket
22620Sigor@sysoev.ru      * descriptors start from number 3 and are sequential.
22720Sigor@sysoev.ru      */
22820Sigor@sysoev.ru     nfd = (u_char *) getenv("LISTEN_FDS");
22920Sigor@sysoev.ru     if (nfd == NULL) {
23020Sigor@sysoev.ru         return NXT_OK;
23120Sigor@sysoev.ru     }
23220Sigor@sysoev.ru 
23320Sigor@sysoev.ru     /* The pid of the service process. */
23420Sigor@sysoev.ru     pid = (u_char *) getenv("LISTEN_PID");
23520Sigor@sysoev.ru     if (pid == NULL) {
23620Sigor@sysoev.ru         return NXT_OK;
23720Sigor@sysoev.ru     }
23820Sigor@sysoev.ru 
23920Sigor@sysoev.ru     n = nxt_int_parse(nfd, nxt_strlen(nfd));
24020Sigor@sysoev.ru     if (n < 0) {
24120Sigor@sysoev.ru         return NXT_OK;
24220Sigor@sysoev.ru     }
24320Sigor@sysoev.ru 
24420Sigor@sysoev.ru     if (nxt_pid != nxt_int_parse(pid, nxt_strlen(pid))) {
24520Sigor@sysoev.ru         return NXT_OK;
24620Sigor@sysoev.ru     }
24720Sigor@sysoev.ru 
248494Spluknet@nginx.com     nxt_log(task, NXT_LOG_INFO, "using %i systemd listen sockets", n);
24920Sigor@sysoev.ru 
25020Sigor@sysoev.ru     inherited_sockets = nxt_array_create(rt->mem_pool,
25120Sigor@sysoev.ru                                          n, sizeof(nxt_listen_socket_t));
25220Sigor@sysoev.ru     if (inherited_sockets == NULL) {
25320Sigor@sysoev.ru         return NXT_ERROR;
25420Sigor@sysoev.ru     }
25520Sigor@sysoev.ru 
25620Sigor@sysoev.ru     rt->inherited_sockets = inherited_sockets;
25720Sigor@sysoev.ru 
25820Sigor@sysoev.ru     for (s = 3; s < n; s++) {
25920Sigor@sysoev.ru         ls = nxt_array_zero_add(inherited_sockets);
26020Sigor@sysoev.ru         if (nxt_slow_path(ls == NULL)) {
26120Sigor@sysoev.ru             return NXT_ERROR;
26220Sigor@sysoev.ru         }
26320Sigor@sysoev.ru 
26420Sigor@sysoev.ru         ls->socket = s;
26520Sigor@sysoev.ru 
26620Sigor@sysoev.ru         ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s);
26720Sigor@sysoev.ru         if (nxt_slow_path(ls->sockaddr == NULL)) {
26820Sigor@sysoev.ru             return NXT_ERROR;
26920Sigor@sysoev.ru         }
27020Sigor@sysoev.ru 
27120Sigor@sysoev.ru         ls->sockaddr->type = SOCK_STREAM;
27220Sigor@sysoev.ru     }
27320Sigor@sysoev.ru 
27420Sigor@sysoev.ru     return NXT_OK;
27520Sigor@sysoev.ru }
27620Sigor@sysoev.ru 
27720Sigor@sysoev.ru 
27820Sigor@sysoev.ru static nxt_int_t
nxt_runtime_event_engines(nxt_task_t * task,nxt_runtime_t * rt)27920Sigor@sysoev.ru nxt_runtime_event_engines(nxt_task_t *task, nxt_runtime_t *rt)
28020Sigor@sysoev.ru {
28153Sigor@sysoev.ru     nxt_thread_t                 *thread;
28253Sigor@sysoev.ru     nxt_event_engine_t           *engine;
28320Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
28420Sigor@sysoev.ru 
28520Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", NULL);
28620Sigor@sysoev.ru 
28720Sigor@sysoev.ru     if (nxt_slow_path(interface == NULL)) {
28820Sigor@sysoev.ru         /* TODO: log */
28920Sigor@sysoev.ru         return NXT_ERROR;
29020Sigor@sysoev.ru     }
29120Sigor@sysoev.ru 
29220Sigor@sysoev.ru     engine = nxt_event_engine_create(task, interface,
293240Sigor@sysoev.ru                                      nxt_main_process_signals, 0, 0);
29420Sigor@sysoev.ru 
29520Sigor@sysoev.ru     if (nxt_slow_path(engine == NULL)) {
29620Sigor@sysoev.ru         return NXT_ERROR;
29720Sigor@sysoev.ru     }
29820Sigor@sysoev.ru 
29953Sigor@sysoev.ru     thread = task->thread;
30053Sigor@sysoev.ru     thread->engine = engine;
301326Svbart@nginx.com #if 0
30253Sigor@sysoev.ru     thread->fiber = &engine->fibers->fiber;
303326Svbart@nginx.com #endif
30453Sigor@sysoev.ru 
30520Sigor@sysoev.ru     engine->id = rt->last_engine_id++;
306342Smax.romanov@nginx.com     engine->mem_pool = nxt_mp_create(1024, 128, 256, 32);
30753Sigor@sysoev.ru 
30853Sigor@sysoev.ru     nxt_queue_init(&rt->engines);
30953Sigor@sysoev.ru     nxt_queue_insert_tail(&rt->engines, &engine->link);
31020Sigor@sysoev.ru 
31120Sigor@sysoev.ru     return NXT_OK;
31220Sigor@sysoev.ru }
31320Sigor@sysoev.ru 
31420Sigor@sysoev.ru 
31520Sigor@sysoev.ru static nxt_int_t
nxt_runtime_thread_pools(nxt_thread_t * thr,nxt_runtime_t * rt)31620Sigor@sysoev.ru nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt)
31720Sigor@sysoev.ru {
31820Sigor@sysoev.ru     nxt_int_t    ret;
31920Sigor@sysoev.ru     nxt_array_t  *thread_pools;
32020Sigor@sysoev.ru 
32120Sigor@sysoev.ru     thread_pools = nxt_array_create(rt->mem_pool, 1,
32220Sigor@sysoev.ru                                     sizeof(nxt_thread_pool_t *));
32320Sigor@sysoev.ru 
32420Sigor@sysoev.ru     if (nxt_slow_path(thread_pools == NULL)) {
32520Sigor@sysoev.ru         return NXT_ERROR;
32620Sigor@sysoev.ru     }
32720Sigor@sysoev.ru 
32820Sigor@sysoev.ru     rt->thread_pools = thread_pools;
32920Sigor@sysoev.ru     ret = nxt_runtime_thread_pool_create(thr, rt, 2, 60000 * 1000000LL);
33020Sigor@sysoev.ru 
33120Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
33220Sigor@sysoev.ru         return NXT_ERROR;
33320Sigor@sysoev.ru     }
33420Sigor@sysoev.ru 
33520Sigor@sysoev.ru     return NXT_OK;
33620Sigor@sysoev.ru }
33720Sigor@sysoev.ru 
33820Sigor@sysoev.ru 
33920Sigor@sysoev.ru static void
nxt_runtime_start(nxt_task_t * task,void * obj,void * data)34020Sigor@sysoev.ru nxt_runtime_start(nxt_task_t *task, void *obj, void *data)
34120Sigor@sysoev.ru {
34220Sigor@sysoev.ru     nxt_runtime_t  *rt;
34320Sigor@sysoev.ru 
34420Sigor@sysoev.ru     rt = obj;
34520Sigor@sysoev.ru 
34620Sigor@sysoev.ru     nxt_debug(task, "rt conf done");
34720Sigor@sysoev.ru 
34820Sigor@sysoev.ru     task->thread->log->ctx_handler = NULL;
34920Sigor@sysoev.ru     task->thread->log->ctx = NULL;
35020Sigor@sysoev.ru 
35120Sigor@sysoev.ru     if (nxt_runtime_log_files_create(task, rt) != NXT_OK) {
35220Sigor@sysoev.ru         goto fail;
35320Sigor@sysoev.ru     }
35420Sigor@sysoev.ru 
35520Sigor@sysoev.ru     if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) {
35620Sigor@sysoev.ru         goto fail;
35720Sigor@sysoev.ru     }
35820Sigor@sysoev.ru 
35920Sigor@sysoev.ru     /*
36020Sigor@sysoev.ru      * Thread pools should be destroyed before starting worker
36120Sigor@sysoev.ru      * processes, because thread pool semaphores will stick in
36220Sigor@sysoev.ru      * locked state in new processes after fork().
36320Sigor@sysoev.ru      */
36420Sigor@sysoev.ru     nxt_runtime_thread_pool_destroy(task, rt, rt->start);
36520Sigor@sysoev.ru 
36620Sigor@sysoev.ru     return;
36720Sigor@sysoev.ru 
36820Sigor@sysoev.ru fail:
36920Sigor@sysoev.ru 
370697Sigor@sysoev.ru     nxt_runtime_quit(task, 1);
37120Sigor@sysoev.ru }
37220Sigor@sysoev.ru 
37320Sigor@sysoev.ru 
37420Sigor@sysoev.ru static void
nxt_runtime_initial_start(nxt_task_t * task,nxt_uint_t status)375697Sigor@sysoev.ru nxt_runtime_initial_start(nxt_task_t *task, nxt_uint_t status)
37620Sigor@sysoev.ru {
37720Sigor@sysoev.ru     nxt_int_t                    ret;
37820Sigor@sysoev.ru     nxt_thread_t                 *thr;
37920Sigor@sysoev.ru     nxt_runtime_t                *rt;
38020Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
38120Sigor@sysoev.ru 
38220Sigor@sysoev.ru     thr = task->thread;
38320Sigor@sysoev.ru     rt = thr->runtime;
38420Sigor@sysoev.ru 
38520Sigor@sysoev.ru     if (rt->inherited_sockets == NULL && rt->daemon) {
38620Sigor@sysoev.ru 
38720Sigor@sysoev.ru         if (nxt_process_daemon(task) != NXT_OK) {
38820Sigor@sysoev.ru             goto fail;
38920Sigor@sysoev.ru         }
39020Sigor@sysoev.ru 
39120Sigor@sysoev.ru         /*
39220Sigor@sysoev.ru          * An event engine should be updated after fork()
39320Sigor@sysoev.ru          * even if an event facility was not changed because:
39420Sigor@sysoev.ru          * 1) inherited kqueue descriptor is invalid,
39520Sigor@sysoev.ru          * 2) the signal thread is not inherited.
39620Sigor@sysoev.ru          */
39720Sigor@sysoev.ru         interface = nxt_service_get(rt->services, "engine", rt->engine);
39820Sigor@sysoev.ru         if (interface == NULL) {
39920Sigor@sysoev.ru             goto fail;
40020Sigor@sysoev.ru         }
40120Sigor@sysoev.ru 
40220Sigor@sysoev.ru         ret = nxt_event_engine_change(task->thread->engine, interface,
40320Sigor@sysoev.ru                                       rt->batch);
40420Sigor@sysoev.ru         if (ret != NXT_OK) {
40520Sigor@sysoev.ru             goto fail;
40620Sigor@sysoev.ru         }
40720Sigor@sysoev.ru     }
40820Sigor@sysoev.ru 
40920Sigor@sysoev.ru     ret = nxt_runtime_pid_file_create(task, rt->pid_file);
41020Sigor@sysoev.ru     if (ret != NXT_OK) {
41120Sigor@sysoev.ru         goto fail;
41220Sigor@sysoev.ru     }
41320Sigor@sysoev.ru 
41420Sigor@sysoev.ru     if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) {
41520Sigor@sysoev.ru         goto fail;
41620Sigor@sysoev.ru     }
41720Sigor@sysoev.ru 
41820Sigor@sysoev.ru     thr->engine->max_connections = rt->engine_connections;
41920Sigor@sysoev.ru 
420695Sigor@sysoev.ru     if (nxt_main_process_start(thr, task, rt) != NXT_ERROR) {
42120Sigor@sysoev.ru         return;
42220Sigor@sysoev.ru     }
42320Sigor@sysoev.ru 
42420Sigor@sysoev.ru fail:
42520Sigor@sysoev.ru 
426697Sigor@sysoev.ru     nxt_runtime_quit(task, 1);
42720Sigor@sysoev.ru }
42820Sigor@sysoev.ru 
42920Sigor@sysoev.ru 
43020Sigor@sysoev.ru void
nxt_runtime_quit(nxt_task_t * task,nxt_uint_t status)431697Sigor@sysoev.ru nxt_runtime_quit(nxt_task_t *task, nxt_uint_t status)
43220Sigor@sysoev.ru {
43320Sigor@sysoev.ru     nxt_bool_t          done;
43420Sigor@sysoev.ru     nxt_runtime_t       *rt;
43520Sigor@sysoev.ru     nxt_event_engine_t  *engine;
43620Sigor@sysoev.ru 
43720Sigor@sysoev.ru     rt = task->thread->runtime;
438697Sigor@sysoev.ru     rt->status |= status;
43920Sigor@sysoev.ru     engine = task->thread->engine;
44020Sigor@sysoev.ru 
44120Sigor@sysoev.ru     nxt_debug(task, "exiting");
44220Sigor@sysoev.ru 
44320Sigor@sysoev.ru     done = 1;
44420Sigor@sysoev.ru 
44520Sigor@sysoev.ru     if (!engine->shutdown) {
44620Sigor@sysoev.ru         engine->shutdown = 1;
44720Sigor@sysoev.ru 
44820Sigor@sysoev.ru         if (!nxt_array_is_empty(rt->thread_pools)) {
44920Sigor@sysoev.ru             nxt_runtime_thread_pool_destroy(task, rt, nxt_runtime_quit);
45020Sigor@sysoev.ru             done = 0;
45120Sigor@sysoev.ru         }
45220Sigor@sysoev.ru 
453696Sigor@sysoev.ru         if (rt->type == NXT_PROCESS_MAIN) {
4541488St.nateldemoura@f5.com             nxt_runtime_stop_all_processes(task, rt);
45520Sigor@sysoev.ru             done = 0;
45620Sigor@sysoev.ru         }
45720Sigor@sysoev.ru     }
45820Sigor@sysoev.ru 
45920Sigor@sysoev.ru     nxt_runtime_close_idle_connections(engine);
46020Sigor@sysoev.ru 
46120Sigor@sysoev.ru     if (done) {
46220Sigor@sysoev.ru         nxt_work_queue_add(&engine->fast_work_queue, nxt_runtime_exit,
46320Sigor@sysoev.ru                            task, rt, engine);
46420Sigor@sysoev.ru     }
46520Sigor@sysoev.ru }
46620Sigor@sysoev.ru 
46720Sigor@sysoev.ru 
46820Sigor@sysoev.ru static void
nxt_runtime_close_idle_connections(nxt_event_engine_t * engine)46920Sigor@sysoev.ru nxt_runtime_close_idle_connections(nxt_event_engine_t *engine)
47020Sigor@sysoev.ru {
47162Sigor@sysoev.ru     nxt_conn_t        *c;
47220Sigor@sysoev.ru     nxt_queue_t       *idle;
47320Sigor@sysoev.ru     nxt_queue_link_t  *link, *next;
47420Sigor@sysoev.ru 
47520Sigor@sysoev.ru     nxt_debug(&engine->task, "close idle connections");
47620Sigor@sysoev.ru 
47720Sigor@sysoev.ru     idle = &engine->idle_connections;
47820Sigor@sysoev.ru 
4791238Smax.romanov@nginx.com     for (link = nxt_queue_first(idle);
48020Sigor@sysoev.ru          link != nxt_queue_tail(idle);
48120Sigor@sysoev.ru          link = next)
48220Sigor@sysoev.ru     {
48320Sigor@sysoev.ru         next = nxt_queue_next(link);
48462Sigor@sysoev.ru         c = nxt_queue_link_data(link, nxt_conn_t, link);
48520Sigor@sysoev.ru 
48620Sigor@sysoev.ru         if (!c->socket.read_ready) {
48720Sigor@sysoev.ru             nxt_queue_remove(link);
48862Sigor@sysoev.ru             nxt_conn_close(engine, c);
48920Sigor@sysoev.ru         }
49020Sigor@sysoev.ru     }
49120Sigor@sysoev.ru }
49220Sigor@sysoev.ru 
49320Sigor@sysoev.ru 
4941488St.nateldemoura@f5.com void
nxt_runtime_stop_app_processes(nxt_task_t * task,nxt_runtime_t * rt)4951488St.nateldemoura@f5.com nxt_runtime_stop_app_processes(nxt_task_t *task, nxt_runtime_t *rt)
4961488St.nateldemoura@f5.com {
4971488St.nateldemoura@f5.com     nxt_port_t          *port;
4981488St.nateldemoura@f5.com     nxt_process_t       *process;
4991488St.nateldemoura@f5.com     nxt_process_init_t  *init;
5001488St.nateldemoura@f5.com 
5011488St.nateldemoura@f5.com     nxt_runtime_process_each(rt, process) {
5021488St.nateldemoura@f5.com 
5031488St.nateldemoura@f5.com         init = nxt_process_init(process);
5041488St.nateldemoura@f5.com 
505*1998St.nateldemoura@f5.com         if (init->type == NXT_PROCESS_APP
506*1998St.nateldemoura@f5.com             || init->type == NXT_PROCESS_PROTOTYPE)
507*1998St.nateldemoura@f5.com         {
5081488St.nateldemoura@f5.com 
5091488St.nateldemoura@f5.com             nxt_process_port_each(process, port) {
5101488St.nateldemoura@f5.com 
5111488St.nateldemoura@f5.com                 (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1,
5121488St.nateldemoura@f5.com                                              0, 0, NULL);
5131488St.nateldemoura@f5.com 
5141488St.nateldemoura@f5.com             } nxt_process_port_loop;
5151488St.nateldemoura@f5.com         }
5161488St.nateldemoura@f5.com 
5171488St.nateldemoura@f5.com     } nxt_runtime_process_loop;
5181488St.nateldemoura@f5.com }
5191488St.nateldemoura@f5.com 
5201488St.nateldemoura@f5.com 
5211488St.nateldemoura@f5.com static void
nxt_runtime_stop_all_processes(nxt_task_t * task,nxt_runtime_t * rt)5221488St.nateldemoura@f5.com nxt_runtime_stop_all_processes(nxt_task_t *task, nxt_runtime_t *rt)
5231488St.nateldemoura@f5.com {
5241488St.nateldemoura@f5.com     nxt_port_t     *port;
5251488St.nateldemoura@f5.com     nxt_process_t  *process;
5261488St.nateldemoura@f5.com 
5271488St.nateldemoura@f5.com     nxt_runtime_process_each(rt, process) {
5281488St.nateldemoura@f5.com 
5291488St.nateldemoura@f5.com         nxt_process_port_each(process, port) {
5301488St.nateldemoura@f5.com 
531*1998St.nateldemoura@f5.com             nxt_debug(task, "%d sending quit to %PI", rt->type, port->pid);
532*1998St.nateldemoura@f5.com 
5331488St.nateldemoura@f5.com             (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0,
5341488St.nateldemoura@f5.com                                          0, NULL);
5351488St.nateldemoura@f5.com 
5361488St.nateldemoura@f5.com         } nxt_process_port_loop;
5371488St.nateldemoura@f5.com 
5381488St.nateldemoura@f5.com     } nxt_runtime_process_loop;
5391488St.nateldemoura@f5.com }
5401488St.nateldemoura@f5.com 
5411488St.nateldemoura@f5.com 
54220Sigor@sysoev.ru static void
nxt_runtime_exit(nxt_task_t * task,void * obj,void * data)54320Sigor@sysoev.ru nxt_runtime_exit(nxt_task_t *task, void *obj, void *data)
54420Sigor@sysoev.ru {
5451520Smax.romanov@nginx.com     int                 status, engine_count;
546125Smax.romanov@nginx.com     nxt_runtime_t       *rt;
547125Smax.romanov@nginx.com     nxt_process_t       *process;
54820Sigor@sysoev.ru     nxt_event_engine_t  *engine;
54920Sigor@sysoev.ru 
55020Sigor@sysoev.ru     rt = obj;
55120Sigor@sysoev.ru     engine = data;
55220Sigor@sysoev.ru 
55320Sigor@sysoev.ru     nxt_debug(task, "thread pools: %d", rt->thread_pools->nelts);
55420Sigor@sysoev.ru 
55520Sigor@sysoev.ru     if (!nxt_array_is_empty(rt->thread_pools)) {
55620Sigor@sysoev.ru         return;
55720Sigor@sysoev.ru     }
55820Sigor@sysoev.ru 
559696Sigor@sysoev.ru     if (rt->type == NXT_PROCESS_MAIN) {
56020Sigor@sysoev.ru         if (rt->pid_file != NULL) {
56120Sigor@sysoev.ru             nxt_file_delete(rt->pid_file);
56220Sigor@sysoev.ru         }
563234Sigor@sysoev.ru 
564234Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
565234Sigor@sysoev.ru         {
566234Sigor@sysoev.ru             nxt_sockaddr_t   *sa;
567234Sigor@sysoev.ru             nxt_file_name_t  *name;
568234Sigor@sysoev.ru 
569234Sigor@sysoev.ru             sa = rt->controller_listen;
570234Sigor@sysoev.ru 
571234Sigor@sysoev.ru             if (sa->u.sockaddr.sa_family == AF_UNIX) {
572234Sigor@sysoev.ru                 name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path;
573234Sigor@sysoev.ru                 (void) nxt_file_delete(name);
574234Sigor@sysoev.ru             }
575234Sigor@sysoev.ru         }
576234Sigor@sysoev.ru #endif
57720Sigor@sysoev.ru     }
57820Sigor@sysoev.ru 
57920Sigor@sysoev.ru     if (!engine->event.signal_support) {
58020Sigor@sysoev.ru         nxt_event_engine_signals_stop(engine);
58120Sigor@sysoev.ru     }
58220Sigor@sysoev.ru 
583125Smax.romanov@nginx.com     nxt_runtime_process_each(rt, process) {
584125Smax.romanov@nginx.com 
5851997St.nateldemoura@f5.com         nxt_runtime_process_remove(rt, process);
586349Smax.romanov@nginx.com         nxt_process_close_ports(task, process);
587125Smax.romanov@nginx.com 
588125Smax.romanov@nginx.com     } nxt_runtime_process_loop;
589125Smax.romanov@nginx.com 
5901520Smax.romanov@nginx.com     status = rt->status;
5911520Smax.romanov@nginx.com 
5921520Smax.romanov@nginx.com     engine_count = 0;
5931520Smax.romanov@nginx.com 
5941520Smax.romanov@nginx.com     nxt_queue_each(engine, &rt->engines, nxt_event_engine_t, link) {
5951520Smax.romanov@nginx.com 
5961520Smax.romanov@nginx.com         engine_count++;
5971520Smax.romanov@nginx.com 
5981520Smax.romanov@nginx.com     } nxt_queue_loop;
5991488St.nateldemoura@f5.com 
6001520Smax.romanov@nginx.com     if (engine_count <= 1) {
6011520Smax.romanov@nginx.com         if (rt->port_by_type[rt->type] != NULL) {
6021520Smax.romanov@nginx.com             nxt_port_use(task, rt->port_by_type[rt->type], -1);
6031520Smax.romanov@nginx.com         }
604196Smax.romanov@nginx.com 
6051520Smax.romanov@nginx.com         nxt_thread_mutex_destroy(&rt->processes_mutex);
6061520Smax.romanov@nginx.com 
6071520Smax.romanov@nginx.com         nxt_mp_destroy(rt->mem_pool);
6081520Smax.romanov@nginx.com     }
609125Smax.romanov@nginx.com 
610697Sigor@sysoev.ru     nxt_debug(task, "exit: %d", status);
61120Sigor@sysoev.ru 
612697Sigor@sysoev.ru     exit(status);
61320Sigor@sysoev.ru     nxt_unreachable();
61420Sigor@sysoev.ru }
61520Sigor@sysoev.ru 
61620Sigor@sysoev.ru 
61720Sigor@sysoev.ru static nxt_int_t
nxt_runtime_event_engine_change(nxt_task_t * task,nxt_runtime_t * rt)61820Sigor@sysoev.ru nxt_runtime_event_engine_change(nxt_task_t *task, nxt_runtime_t *rt)
61920Sigor@sysoev.ru {
62020Sigor@sysoev.ru     nxt_event_engine_t           *engine;
62120Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
62220Sigor@sysoev.ru 
62320Sigor@sysoev.ru     engine = task->thread->engine;
62420Sigor@sysoev.ru 
62520Sigor@sysoev.ru     if (engine->batch == rt->batch
62620Sigor@sysoev.ru         && nxt_strcmp(engine->event.name, rt->engine) == 0)
62720Sigor@sysoev.ru     {
62820Sigor@sysoev.ru         return NXT_OK;
62920Sigor@sysoev.ru     }
63020Sigor@sysoev.ru 
63120Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", rt->engine);
63220Sigor@sysoev.ru 
63320Sigor@sysoev.ru     if (interface != NULL) {
63420Sigor@sysoev.ru         return nxt_event_engine_change(engine, interface, rt->batch);
63520Sigor@sysoev.ru     }
63620Sigor@sysoev.ru 
63720Sigor@sysoev.ru     return NXT_ERROR;
63820Sigor@sysoev.ru }
63920Sigor@sysoev.ru 
64020Sigor@sysoev.ru 
64120Sigor@sysoev.ru void
nxt_runtime_event_engine_free(nxt_runtime_t * rt)64220Sigor@sysoev.ru nxt_runtime_event_engine_free(nxt_runtime_t *rt)
64320Sigor@sysoev.ru {
64453Sigor@sysoev.ru     nxt_queue_link_t    *link;
64553Sigor@sysoev.ru     nxt_event_engine_t  *engine;
64620Sigor@sysoev.ru 
64753Sigor@sysoev.ru     link = nxt_queue_first(&rt->engines);
64853Sigor@sysoev.ru     nxt_queue_remove(link);
64920Sigor@sysoev.ru 
65053Sigor@sysoev.ru     engine = nxt_queue_link_data(link, nxt_event_engine_t, link);
65120Sigor@sysoev.ru     nxt_event_engine_free(engine);
65220Sigor@sysoev.ru }
65320Sigor@sysoev.ru 
65420Sigor@sysoev.ru 
65520Sigor@sysoev.ru nxt_int_t
nxt_runtime_thread_pool_create(nxt_thread_t * thr,nxt_runtime_t * rt,nxt_uint_t max_threads,nxt_nsec_t timeout)65620Sigor@sysoev.ru nxt_runtime_thread_pool_create(nxt_thread_t *thr, nxt_runtime_t *rt,
65720Sigor@sysoev.ru     nxt_uint_t max_threads, nxt_nsec_t timeout)
65820Sigor@sysoev.ru {
65920Sigor@sysoev.ru     nxt_thread_pool_t   *thread_pool, **tp;
66020Sigor@sysoev.ru 
66120Sigor@sysoev.ru     tp = nxt_array_add(rt->thread_pools);
66220Sigor@sysoev.ru     if (tp == NULL) {
66320Sigor@sysoev.ru         return NXT_ERROR;
66420Sigor@sysoev.ru     }
66520Sigor@sysoev.ru 
66620Sigor@sysoev.ru     thread_pool = nxt_thread_pool_create(max_threads, timeout,
66720Sigor@sysoev.ru                                          nxt_runtime_thread_pool_init,
66820Sigor@sysoev.ru                                          thr->engine,
66920Sigor@sysoev.ru                                          nxt_runtime_thread_pool_exit);
67020Sigor@sysoev.ru 
67120Sigor@sysoev.ru     if (nxt_fast_path(thread_pool != NULL)) {
67220Sigor@sysoev.ru         *tp = thread_pool;
67320Sigor@sysoev.ru     }
67420Sigor@sysoev.ru 
67520Sigor@sysoev.ru     return NXT_OK;
67620Sigor@sysoev.ru }
67720Sigor@sysoev.ru 
67820Sigor@sysoev.ru 
67920Sigor@sysoev.ru static void
nxt_runtime_thread_pool_destroy(nxt_task_t * task,nxt_runtime_t * rt,nxt_runtime_cont_t cont)68020Sigor@sysoev.ru nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt,
68120Sigor@sysoev.ru     nxt_runtime_cont_t cont)
68220Sigor@sysoev.ru {
68320Sigor@sysoev.ru     nxt_uint_t         n;
68420Sigor@sysoev.ru     nxt_thread_pool_t  **tp;
68520Sigor@sysoev.ru 
68620Sigor@sysoev.ru     rt->continuation = cont;
68720Sigor@sysoev.ru 
68820Sigor@sysoev.ru     n = rt->thread_pools->nelts;
68920Sigor@sysoev.ru 
69020Sigor@sysoev.ru     if (n == 0) {
691697Sigor@sysoev.ru         cont(task, 0);
69220Sigor@sysoev.ru         return;
69320Sigor@sysoev.ru     }
69420Sigor@sysoev.ru 
69520Sigor@sysoev.ru     tp = rt->thread_pools->elts;
69620Sigor@sysoev.ru 
69720Sigor@sysoev.ru     do {
69820Sigor@sysoev.ru         nxt_thread_pool_destroy(*tp);
69920Sigor@sysoev.ru 
70020Sigor@sysoev.ru         tp++;
70120Sigor@sysoev.ru         n--;
70220Sigor@sysoev.ru     } while (n != 0);
70320Sigor@sysoev.ru }
70420Sigor@sysoev.ru 
70520Sigor@sysoev.ru 
70620Sigor@sysoev.ru static void
nxt_runtime_thread_pool_init(void)70720Sigor@sysoev.ru nxt_runtime_thread_pool_init(void)
70820Sigor@sysoev.ru {
70920Sigor@sysoev.ru }
71020Sigor@sysoev.ru 
71120Sigor@sysoev.ru 
71220Sigor@sysoev.ru static void
nxt_runtime_thread_pool_exit(nxt_task_t * task,void * obj,void * data)71320Sigor@sysoev.ru nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj, void *data)
71420Sigor@sysoev.ru {
71520Sigor@sysoev.ru     nxt_uint_t           i, n;
71620Sigor@sysoev.ru     nxt_runtime_t        *rt;
71720Sigor@sysoev.ru     nxt_thread_pool_t    *tp, **thread_pools;
71820Sigor@sysoev.ru     nxt_thread_handle_t  handle;
71920Sigor@sysoev.ru 
72020Sigor@sysoev.ru     tp = obj;
72120Sigor@sysoev.ru 
72220Sigor@sysoev.ru     if (data != NULL) {
72320Sigor@sysoev.ru         handle = (nxt_thread_handle_t) (uintptr_t) data;
72420Sigor@sysoev.ru         nxt_thread_wait(handle);
72520Sigor@sysoev.ru     }
72620Sigor@sysoev.ru 
72720Sigor@sysoev.ru     rt = task->thread->runtime;
72820Sigor@sysoev.ru 
72920Sigor@sysoev.ru     thread_pools = rt->thread_pools->elts;
73020Sigor@sysoev.ru     n = rt->thread_pools->nelts;
73120Sigor@sysoev.ru 
73220Sigor@sysoev.ru     nxt_debug(task, "thread pools: %ui", n);
73320Sigor@sysoev.ru 
73420Sigor@sysoev.ru     for (i = 0; i < n; i++) {
73520Sigor@sysoev.ru 
73620Sigor@sysoev.ru         if (tp == thread_pools[i]) {
73720Sigor@sysoev.ru             nxt_array_remove(rt->thread_pools, &thread_pools[i]);
73820Sigor@sysoev.ru 
7391251St.nateldemoura@f5.com             nxt_free(tp);
7401251St.nateldemoura@f5.com 
74120Sigor@sysoev.ru             if (n == 1) {
74220Sigor@sysoev.ru                 /* The last thread pool. */
743697Sigor@sysoev.ru                 rt->continuation(task, 0);
74420Sigor@sysoev.ru             }
74520Sigor@sysoev.ru 
74620Sigor@sysoev.ru             return;
74720Sigor@sysoev.ru         }
74820Sigor@sysoev.ru     }
74920Sigor@sysoev.ru }
75020Sigor@sysoev.ru 
75120Sigor@sysoev.ru 
75220Sigor@sysoev.ru static nxt_int_t
nxt_runtime_conf_init(nxt_task_t * task,nxt_runtime_t * rt)75320Sigor@sysoev.ru nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt)
75420Sigor@sysoev.ru {
75520Sigor@sysoev.ru     nxt_int_t                    ret;
756251Sigor@sysoev.ru     nxt_str_t                    control;
757251Sigor@sysoev.ru     nxt_uint_t                   n;
75820Sigor@sysoev.ru     nxt_file_t                   *file;
759251Sigor@sysoev.ru     const char                   *slash;
760234Sigor@sysoev.ru     nxt_sockaddr_t               *sa;
76120Sigor@sysoev.ru     nxt_file_name_str_t          file_name;
76220Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
76320Sigor@sysoev.ru 
76420Sigor@sysoev.ru     rt->daemon = 1;
76520Sigor@sysoev.ru     rt->engine_connections = 256;
76620Sigor@sysoev.ru     rt->auxiliary_threads = 2;
767232Sigor@sysoev.ru     rt->user_cred.user = NXT_USER;
768232Sigor@sysoev.ru     rt->group = NXT_GROUP;
769231Sigor@sysoev.ru     rt->pid = NXT_PID;
770230Sigor@sysoev.ru     rt->log = NXT_LOG;
771233Sigor@sysoev.ru     rt->modules = NXT_MODULES;
772314Svbart@nginx.com     rt->state = NXT_STATE;
773234Sigor@sysoev.ru     rt->control = NXT_CONTROL_SOCK;
7741403Smax.romanov@nginx.com     rt->tmp = NXT_TMP;
77520Sigor@sysoev.ru 
7761182St.nateldemoura@f5.com     nxt_memzero(&rt->capabilities, sizeof(nxt_capabilities_t));
7771182St.nateldemoura@f5.com 
77820Sigor@sysoev.ru     if (nxt_runtime_conf_read_cmd(task, rt) != NXT_OK) {
77920Sigor@sysoev.ru         return NXT_ERROR;
78020Sigor@sysoev.ru     }
78120Sigor@sysoev.ru 
7821182St.nateldemoura@f5.com     if (nxt_capability_set(task, &rt->capabilities) != NXT_OK) {
78320Sigor@sysoev.ru         return NXT_ERROR;
78420Sigor@sysoev.ru     }
78520Sigor@sysoev.ru 
7861182St.nateldemoura@f5.com     if (rt->capabilities.setid) {
7871305St.nateldemoura@f5.com         ret = nxt_credential_get(task, rt->mem_pool, &rt->user_cred,
7881302St.nateldemoura@f5.com                                 rt->group);
7891302St.nateldemoura@f5.com 
7901302St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
7911182St.nateldemoura@f5.com             return NXT_ERROR;
7921182St.nateldemoura@f5.com         }
7931182St.nateldemoura@f5.com 
7941182St.nateldemoura@f5.com     } else {
7951182St.nateldemoura@f5.com         nxt_log(task, NXT_LOG_WARN, "Unit is running unprivileged, then it "
7961182St.nateldemoura@f5.com                 "cannot use arbitrary user and group.");
7971182St.nateldemoura@f5.com     }
7981182St.nateldemoura@f5.com 
79920Sigor@sysoev.ru     /* An engine's parameters. */
80020Sigor@sysoev.ru 
80120Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", rt->engine);
80220Sigor@sysoev.ru     if (interface == NULL) {
80320Sigor@sysoev.ru         return NXT_ERROR;
80420Sigor@sysoev.ru     }
80520Sigor@sysoev.ru 
80620Sigor@sysoev.ru     rt->engine = interface->name;
80720Sigor@sysoev.ru 
808252Smax.romanov@nginx.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->pid);
80920Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
81020Sigor@sysoev.ru         return NXT_ERROR;
81120Sigor@sysoev.ru     }
81220Sigor@sysoev.ru 
81320Sigor@sysoev.ru     rt->pid_file = file_name.start;
81420Sigor@sysoev.ru 
815230Sigor@sysoev.ru     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->log);
81620Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
81720Sigor@sysoev.ru         return NXT_ERROR;
81820Sigor@sysoev.ru     }
81920Sigor@sysoev.ru 
82020Sigor@sysoev.ru     file = nxt_list_first(rt->log_files);
82120Sigor@sysoev.ru     file->name = file_name.start;
82220Sigor@sysoev.ru 
823251Sigor@sysoev.ru     slash = "";
824251Sigor@sysoev.ru     n = nxt_strlen(rt->modules);
825251Sigor@sysoev.ru 
826251Sigor@sysoev.ru     if (n > 1 && rt->modules[n - 1] != '/') {
827251Sigor@sysoev.ru         slash = "/";
828251Sigor@sysoev.ru     }
829251Sigor@sysoev.ru 
830260Sigor@sysoev.ru     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%s*.unit.so%Z",
831251Sigor@sysoev.ru                                rt->modules, slash);
832233Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
833233Sigor@sysoev.ru         return NXT_ERROR;
834233Sigor@sysoev.ru     }
835233Sigor@sysoev.ru 
836233Sigor@sysoev.ru     rt->modules = (char *) file_name.start;
837233Sigor@sysoev.ru 
838314Svbart@nginx.com     slash = "";
839314Svbart@nginx.com     n = nxt_strlen(rt->state);
840314Svbart@nginx.com 
841314Svbart@nginx.com     if (n > 1 && rt->state[n - 1] != '/') {
842314Svbart@nginx.com         slash = "/";
843314Svbart@nginx.com     }
844314Svbart@nginx.com 
8451969Sz.hong@f5.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sversion%Z",
8461969Sz.hong@f5.com                                rt->state, slash);
8471969Sz.hong@f5.com     if (nxt_slow_path(ret != NXT_OK)) {
8481969Sz.hong@f5.com         return NXT_ERROR;
8491969Sz.hong@f5.com     }
8501969Sz.hong@f5.com 
8511969Sz.hong@f5.com     rt->ver = (char *) file_name.start;
8521969Sz.hong@f5.com 
8531969Sz.hong@f5.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s.tmp%Z", rt->ver);
8541969Sz.hong@f5.com     if (nxt_slow_path(ret != NXT_OK)) {
8551969Sz.hong@f5.com         return NXT_ERROR;
8561969Sz.hong@f5.com     }
8571969Sz.hong@f5.com 
8581969Sz.hong@f5.com     rt->ver_tmp = (char *) file_name.start;
8591969Sz.hong@f5.com 
860314Svbart@nginx.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sconf.json%Z",
861314Svbart@nginx.com                                rt->state, slash);
862314Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
863314Svbart@nginx.com         return NXT_ERROR;
864314Svbart@nginx.com     }
865314Svbart@nginx.com 
866314Svbart@nginx.com     rt->conf = (char *) file_name.start;
867314Svbart@nginx.com 
868314Svbart@nginx.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s.tmp%Z", rt->conf);
869314Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
870314Svbart@nginx.com         return NXT_ERROR;
871314Svbart@nginx.com     }
872314Svbart@nginx.com 
873314Svbart@nginx.com     rt->conf_tmp = (char *) file_name.start;
874314Svbart@nginx.com 
875774Svbart@nginx.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%scerts/%Z",
876774Svbart@nginx.com                                rt->state, slash);
877774Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
878774Svbart@nginx.com         return NXT_ERROR;
879774Svbart@nginx.com     }
880774Svbart@nginx.com 
881774Svbart@nginx.com     ret = mkdir((char *) file_name.start, S_IRWXU);
882774Svbart@nginx.com 
883774Svbart@nginx.com     if (nxt_fast_path(ret == 0 || nxt_errno == EEXIST)) {
884774Svbart@nginx.com         rt->certs.length = file_name.len;
885774Svbart@nginx.com         rt->certs.start = file_name.start;
886774Svbart@nginx.com 
887774Svbart@nginx.com     } else {
888774Svbart@nginx.com         nxt_alert(task, "Unable to create certificates storage directory: "
889774Svbart@nginx.com                   "mkdir(%s) failed %E", file_name.start, nxt_errno);
890774Svbart@nginx.com     }
891774Svbart@nginx.com 
892234Sigor@sysoev.ru     control.length = nxt_strlen(rt->control);
893234Sigor@sysoev.ru     control.start = (u_char *) rt->control;
894234Sigor@sysoev.ru 
895649Svbart@nginx.com     sa = nxt_sockaddr_parse(rt->mem_pool, &control);
896234Sigor@sysoev.ru     if (nxt_slow_path(sa == NULL)) {
897234Sigor@sysoev.ru         return NXT_ERROR;
898234Sigor@sysoev.ru     }
899234Sigor@sysoev.ru 
900649Svbart@nginx.com     sa->type = SOCK_STREAM;
901649Svbart@nginx.com 
902234Sigor@sysoev.ru     rt->controller_listen = sa;
903234Sigor@sysoev.ru 
904234Sigor@sysoev.ru     if (nxt_runtime_controller_socket(task, rt) != NXT_OK) {
905234Sigor@sysoev.ru         return NXT_ERROR;
906234Sigor@sysoev.ru     }
907234Sigor@sysoev.ru 
90820Sigor@sysoev.ru     return NXT_OK;
90920Sigor@sysoev.ru }
91020Sigor@sysoev.ru 
91120Sigor@sysoev.ru 
91220Sigor@sysoev.ru static nxt_int_t
nxt_runtime_conf_read_cmd(nxt_task_t * task,nxt_runtime_t * rt)91320Sigor@sysoev.ru nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt)
91420