xref: /unit/src/nxt_runtime.c (revision 1182)
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>
1320Sigor@sysoev.ru 
1420Sigor@sysoev.ru 
1520Sigor@sysoev.ru static nxt_int_t nxt_runtime_inherited_listen_sockets(nxt_task_t *task,
1620Sigor@sysoev.ru     nxt_runtime_t *rt);
1720Sigor@sysoev.ru static nxt_int_t nxt_runtime_systemd_listen_sockets(nxt_task_t *task,
1820Sigor@sysoev.ru     nxt_runtime_t *rt);
1920Sigor@sysoev.ru static nxt_int_t nxt_runtime_event_engines(nxt_task_t *task, nxt_runtime_t *rt);
2020Sigor@sysoev.ru static nxt_int_t nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt);
2120Sigor@sysoev.ru static void nxt_runtime_start(nxt_task_t *task, void *obj, void *data);
22697Sigor@sysoev.ru static void nxt_runtime_initial_start(nxt_task_t *task, nxt_uint_t status);
2320Sigor@sysoev.ru static void nxt_runtime_close_idle_connections(nxt_event_engine_t *engine);
2420Sigor@sysoev.ru static void nxt_runtime_exit(nxt_task_t *task, void *obj, void *data);
2520Sigor@sysoev.ru static nxt_int_t nxt_runtime_event_engine_change(nxt_task_t *task,
2620Sigor@sysoev.ru     nxt_runtime_t *rt);
2720Sigor@sysoev.ru static nxt_int_t nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt);
2820Sigor@sysoev.ru static nxt_int_t nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt);
2920Sigor@sysoev.ru static nxt_int_t nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt);
3020Sigor@sysoev.ru static nxt_int_t nxt_runtime_log_files_init(nxt_runtime_t *rt);
3120Sigor@sysoev.ru static nxt_int_t nxt_runtime_log_files_create(nxt_task_t *task,
3220Sigor@sysoev.ru     nxt_runtime_t *rt);
3320Sigor@sysoev.ru static nxt_int_t nxt_runtime_pid_file_create(nxt_task_t *task,
3420Sigor@sysoev.ru     nxt_file_name_t *pid_file);
3520Sigor@sysoev.ru static void nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt,
3620Sigor@sysoev.ru     nxt_runtime_cont_t cont);
37223Sigor@sysoev.ru static void nxt_runtime_thread_pool_init(void);
38223Sigor@sysoev.ru static void nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj,
39223Sigor@sysoev.ru     void *data);
40196Smax.romanov@nginx.com static void nxt_runtime_process_destroy(nxt_runtime_t *rt,
41196Smax.romanov@nginx.com     nxt_process_t *process);
42196Smax.romanov@nginx.com static nxt_process_t *nxt_runtime_process_remove_pid(nxt_runtime_t *rt,
43196Smax.romanov@nginx.com     nxt_pid_t pid);
44196Smax.romanov@nginx.com 
4520Sigor@sysoev.ru 
4620Sigor@sysoev.ru nxt_int_t
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;
86216Sigor@sysoev.ru 
8720Sigor@sysoev.ru     listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t));
8820Sigor@sysoev.ru     if (nxt_slow_path(listen_sockets == NULL)) {
8920Sigor@sysoev.ru         goto fail;
9020Sigor@sysoev.ru     }
9120Sigor@sysoev.ru 
9220Sigor@sysoev.ru     rt->listen_sockets = listen_sockets;
9320Sigor@sysoev.ru 
9420Sigor@sysoev.ru     ret = nxt_runtime_inherited_listen_sockets(task, rt);
9520Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
9620Sigor@sysoev.ru         goto fail;
9720Sigor@sysoev.ru     }
9820Sigor@sysoev.ru 
9920Sigor@sysoev.ru     if (nxt_runtime_hostname(task, rt) != NXT_OK) {
10020Sigor@sysoev.ru         goto fail;
10120Sigor@sysoev.ru     }
10220Sigor@sysoev.ru 
10320Sigor@sysoev.ru     if (nxt_slow_path(nxt_runtime_log_files_init(rt) != NXT_OK)) {
10420Sigor@sysoev.ru         goto fail;
10520Sigor@sysoev.ru     }
10620Sigor@sysoev.ru 
10720Sigor@sysoev.ru     if (nxt_runtime_event_engines(task, rt) != NXT_OK) {
10820Sigor@sysoev.ru         goto fail;
10920Sigor@sysoev.ru     }
11020Sigor@sysoev.ru 
11120Sigor@sysoev.ru     if (nxt_slow_path(nxt_runtime_thread_pools(task->thread, rt) != NXT_OK)) {
11220Sigor@sysoev.ru         goto fail;
11320Sigor@sysoev.ru     }
11420Sigor@sysoev.ru 
11520Sigor@sysoev.ru     rt->start = nxt_runtime_initial_start;
11620Sigor@sysoev.ru 
117221Sigor@sysoev.ru     if (nxt_runtime_conf_init(task, rt) != NXT_OK) {
118221Sigor@sysoev.ru         goto fail;
119221Sigor@sysoev.ru     }
120221Sigor@sysoev.ru 
12120Sigor@sysoev.ru     nxt_work_queue_add(&task->thread->engine->fast_work_queue,
12220Sigor@sysoev.ru                        nxt_runtime_start, task, rt, NULL);
12320Sigor@sysoev.ru 
12420Sigor@sysoev.ru     return NXT_OK;
12520Sigor@sysoev.ru 
12620Sigor@sysoev.ru fail:
12720Sigor@sysoev.ru 
12865Sigor@sysoev.ru     nxt_mp_destroy(mp);
12920Sigor@sysoev.ru 
13020Sigor@sysoev.ru     return NXT_ERROR;
13120Sigor@sysoev.ru }
13220Sigor@sysoev.ru 
13320Sigor@sysoev.ru 
13420Sigor@sysoev.ru static nxt_int_t
13520Sigor@sysoev.ru nxt_runtime_inherited_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt)
13620Sigor@sysoev.ru {
13720Sigor@sysoev.ru     u_char               *v, *p;
13820Sigor@sysoev.ru     nxt_int_t            type;
13920Sigor@sysoev.ru     nxt_array_t          *inherited_sockets;
14020Sigor@sysoev.ru     nxt_socket_t         s;
14120Sigor@sysoev.ru     nxt_listen_socket_t  *ls;
14220Sigor@sysoev.ru 
14320Sigor@sysoev.ru     v = (u_char *) getenv("NGINX");
14420Sigor@sysoev.ru 
14520Sigor@sysoev.ru     if (v == NULL) {
14620Sigor@sysoev.ru         return nxt_runtime_systemd_listen_sockets(task, rt);
14720Sigor@sysoev.ru     }
14820Sigor@sysoev.ru 
149564Svbart@nginx.com     nxt_alert(task, "using inherited listen sockets: %s", v);
15020Sigor@sysoev.ru 
15120Sigor@sysoev.ru     inherited_sockets = nxt_array_create(rt->mem_pool,
15220Sigor@sysoev.ru                                          1, sizeof(nxt_listen_socket_t));
15320Sigor@sysoev.ru     if (inherited_sockets == NULL) {
15420Sigor@sysoev.ru         return NXT_ERROR;
15520Sigor@sysoev.ru     }
15620Sigor@sysoev.ru 
15720Sigor@sysoev.ru     rt->inherited_sockets = inherited_sockets;
15820Sigor@sysoev.ru 
15920Sigor@sysoev.ru     for (p = v; *p != '\0'; p++) {
16020Sigor@sysoev.ru 
16120Sigor@sysoev.ru         if (*p == ';') {
16220Sigor@sysoev.ru             s = nxt_int_parse(v, p - v);
16320Sigor@sysoev.ru 
16420Sigor@sysoev.ru             if (nxt_slow_path(s < 0)) {
165564Svbart@nginx.com                 nxt_alert(task, "invalid socket number \"%s\" "
166564Svbart@nginx.com                           "in NGINX environment variable, "
167564Svbart@nginx.com                           "ignoring the rest of the variable", v);
16820Sigor@sysoev.ru                 return NXT_ERROR;
16920Sigor@sysoev.ru             }
17020Sigor@sysoev.ru 
17120Sigor@sysoev.ru             v = p + 1;
17220Sigor@sysoev.ru 
17320Sigor@sysoev.ru             ls = nxt_array_zero_add(inherited_sockets);
17420Sigor@sysoev.ru             if (nxt_slow_path(ls == NULL)) {
17520Sigor@sysoev.ru                 return NXT_ERROR;
17620Sigor@sysoev.ru             }
17720Sigor@sysoev.ru 
17820Sigor@sysoev.ru             ls->socket = s;
17920Sigor@sysoev.ru 
18020Sigor@sysoev.ru             ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s);
18120Sigor@sysoev.ru             if (nxt_slow_path(ls->sockaddr == NULL)) {
18220Sigor@sysoev.ru                 return NXT_ERROR;
18320Sigor@sysoev.ru             }
18420Sigor@sysoev.ru 
18520Sigor@sysoev.ru             type = nxt_socket_getsockopt(task, s, SOL_SOCKET, SO_TYPE);
18620Sigor@sysoev.ru             if (nxt_slow_path(type == -1)) {
18720Sigor@sysoev.ru                 return NXT_ERROR;
18820Sigor@sysoev.ru             }
18920Sigor@sysoev.ru 
19020Sigor@sysoev.ru             ls->sockaddr->type = (uint16_t) type;
19120Sigor@sysoev.ru         }
19220Sigor@sysoev.ru     }
19320Sigor@sysoev.ru 
19420Sigor@sysoev.ru     return NXT_OK;
19520Sigor@sysoev.ru }
19620Sigor@sysoev.ru 
19720Sigor@sysoev.ru 
19820Sigor@sysoev.ru static nxt_int_t
19920Sigor@sysoev.ru nxt_runtime_systemd_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt)
20020Sigor@sysoev.ru {
20120Sigor@sysoev.ru     u_char               *nfd, *pid;
20220Sigor@sysoev.ru     nxt_int_t            n;
20320Sigor@sysoev.ru     nxt_array_t          *inherited_sockets;
20420Sigor@sysoev.ru     nxt_socket_t         s;
20520Sigor@sysoev.ru     nxt_listen_socket_t  *ls;
20620Sigor@sysoev.ru 
20720Sigor@sysoev.ru     /*
20820Sigor@sysoev.ru      * Number of listening sockets passed.  The socket
20920Sigor@sysoev.ru      * descriptors start from number 3 and are sequential.
21020Sigor@sysoev.ru      */
21120Sigor@sysoev.ru     nfd = (u_char *) getenv("LISTEN_FDS");
21220Sigor@sysoev.ru     if (nfd == NULL) {
21320Sigor@sysoev.ru         return NXT_OK;
21420Sigor@sysoev.ru     }
21520Sigor@sysoev.ru 
21620Sigor@sysoev.ru     /* The pid of the service process. */
21720Sigor@sysoev.ru     pid = (u_char *) getenv("LISTEN_PID");
21820Sigor@sysoev.ru     if (pid == NULL) {
21920Sigor@sysoev.ru         return NXT_OK;
22020Sigor@sysoev.ru     }
22120Sigor@sysoev.ru 
22220Sigor@sysoev.ru     n = nxt_int_parse(nfd, nxt_strlen(nfd));
22320Sigor@sysoev.ru     if (n < 0) {
22420Sigor@sysoev.ru         return NXT_OK;
22520Sigor@sysoev.ru     }
22620Sigor@sysoev.ru 
22720Sigor@sysoev.ru     if (nxt_pid != nxt_int_parse(pid, nxt_strlen(pid))) {
22820Sigor@sysoev.ru         return NXT_OK;
22920Sigor@sysoev.ru     }
23020Sigor@sysoev.ru 
231494Spluknet@nginx.com     nxt_log(task, NXT_LOG_INFO, "using %i systemd listen sockets", n);
23220Sigor@sysoev.ru 
23320Sigor@sysoev.ru     inherited_sockets = nxt_array_create(rt->mem_pool,
23420Sigor@sysoev.ru                                          n, sizeof(nxt_listen_socket_t));
23520Sigor@sysoev.ru     if (inherited_sockets == NULL) {
23620Sigor@sysoev.ru         return NXT_ERROR;
23720Sigor@sysoev.ru     }
23820Sigor@sysoev.ru 
23920Sigor@sysoev.ru     rt->inherited_sockets = inherited_sockets;
24020Sigor@sysoev.ru 
24120Sigor@sysoev.ru     for (s = 3; s < n; s++) {
24220Sigor@sysoev.ru         ls = nxt_array_zero_add(inherited_sockets);
24320Sigor@sysoev.ru         if (nxt_slow_path(ls == NULL)) {
24420Sigor@sysoev.ru             return NXT_ERROR;
24520Sigor@sysoev.ru         }
24620Sigor@sysoev.ru 
24720Sigor@sysoev.ru         ls->socket = s;
24820Sigor@sysoev.ru 
24920Sigor@sysoev.ru         ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s);
25020Sigor@sysoev.ru         if (nxt_slow_path(ls->sockaddr == NULL)) {
25120Sigor@sysoev.ru             return NXT_ERROR;
25220Sigor@sysoev.ru         }
25320Sigor@sysoev.ru 
25420Sigor@sysoev.ru         ls->sockaddr->type = SOCK_STREAM;
25520Sigor@sysoev.ru     }
25620Sigor@sysoev.ru 
25720Sigor@sysoev.ru     return NXT_OK;
25820Sigor@sysoev.ru }
25920Sigor@sysoev.ru 
26020Sigor@sysoev.ru 
26120Sigor@sysoev.ru static nxt_int_t
26220Sigor@sysoev.ru nxt_runtime_event_engines(nxt_task_t *task, nxt_runtime_t *rt)
26320Sigor@sysoev.ru {
26453Sigor@sysoev.ru     nxt_thread_t                 *thread;
26553Sigor@sysoev.ru     nxt_event_engine_t           *engine;
26620Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
26720Sigor@sysoev.ru 
26820Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", NULL);
26920Sigor@sysoev.ru 
27020Sigor@sysoev.ru     if (nxt_slow_path(interface == NULL)) {
27120Sigor@sysoev.ru         /* TODO: log */
27220Sigor@sysoev.ru         return NXT_ERROR;
27320Sigor@sysoev.ru     }
27420Sigor@sysoev.ru 
27520Sigor@sysoev.ru     engine = nxt_event_engine_create(task, interface,
276240Sigor@sysoev.ru                                      nxt_main_process_signals, 0, 0);
27720Sigor@sysoev.ru 
27820Sigor@sysoev.ru     if (nxt_slow_path(engine == NULL)) {
27920Sigor@sysoev.ru         return NXT_ERROR;
28020Sigor@sysoev.ru     }
28120Sigor@sysoev.ru 
28253Sigor@sysoev.ru     thread = task->thread;
28353Sigor@sysoev.ru     thread->engine = engine;
284326Svbart@nginx.com #if 0
28553Sigor@sysoev.ru     thread->fiber = &engine->fibers->fiber;
286326Svbart@nginx.com #endif
28753Sigor@sysoev.ru 
28820Sigor@sysoev.ru     engine->id = rt->last_engine_id++;
289342Smax.romanov@nginx.com     engine->mem_pool = nxt_mp_create(1024, 128, 256, 32);
29053Sigor@sysoev.ru 
29153Sigor@sysoev.ru     nxt_queue_init(&rt->engines);
29253Sigor@sysoev.ru     nxt_queue_insert_tail(&rt->engines, &engine->link);
29320Sigor@sysoev.ru 
29420Sigor@sysoev.ru     return NXT_OK;
29520Sigor@sysoev.ru }
29620Sigor@sysoev.ru 
29720Sigor@sysoev.ru 
29820Sigor@sysoev.ru static nxt_int_t
29920Sigor@sysoev.ru nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt)
30020Sigor@sysoev.ru {
30120Sigor@sysoev.ru     nxt_int_t    ret;
30220Sigor@sysoev.ru     nxt_array_t  *thread_pools;
30320Sigor@sysoev.ru 
30420Sigor@sysoev.ru     thread_pools = nxt_array_create(rt->mem_pool, 1,
30520Sigor@sysoev.ru                                     sizeof(nxt_thread_pool_t *));
30620Sigor@sysoev.ru 
30720Sigor@sysoev.ru     if (nxt_slow_path(thread_pools == NULL)) {
30820Sigor@sysoev.ru         return NXT_ERROR;
30920Sigor@sysoev.ru     }
31020Sigor@sysoev.ru 
31120Sigor@sysoev.ru     rt->thread_pools = thread_pools;
31220Sigor@sysoev.ru     ret = nxt_runtime_thread_pool_create(thr, rt, 2, 60000 * 1000000LL);
31320Sigor@sysoev.ru 
31420Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
31520Sigor@sysoev.ru         return NXT_ERROR;
31620Sigor@sysoev.ru     }
31720Sigor@sysoev.ru 
31820Sigor@sysoev.ru     return NXT_OK;
31920Sigor@sysoev.ru }
32020Sigor@sysoev.ru 
32120Sigor@sysoev.ru 
32220Sigor@sysoev.ru static void
32320Sigor@sysoev.ru nxt_runtime_start(nxt_task_t *task, void *obj, void *data)
32420Sigor@sysoev.ru {
32520Sigor@sysoev.ru     nxt_runtime_t  *rt;
32620Sigor@sysoev.ru 
32720Sigor@sysoev.ru     rt = obj;
32820Sigor@sysoev.ru 
32920Sigor@sysoev.ru     nxt_debug(task, "rt conf done");
33020Sigor@sysoev.ru 
33120Sigor@sysoev.ru     task->thread->log->ctx_handler = NULL;
33220Sigor@sysoev.ru     task->thread->log->ctx = NULL;
33320Sigor@sysoev.ru 
33420Sigor@sysoev.ru     if (nxt_runtime_log_files_create(task, rt) != NXT_OK) {
33520Sigor@sysoev.ru         goto fail;
33620Sigor@sysoev.ru     }
33720Sigor@sysoev.ru 
33820Sigor@sysoev.ru     if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) {
33920Sigor@sysoev.ru         goto fail;
34020Sigor@sysoev.ru     }
34120Sigor@sysoev.ru 
34220Sigor@sysoev.ru     /*
34320Sigor@sysoev.ru      * Thread pools should be destroyed before starting worker
34420Sigor@sysoev.ru      * processes, because thread pool semaphores will stick in
34520Sigor@sysoev.ru      * locked state in new processes after fork().
34620Sigor@sysoev.ru      */
34720Sigor@sysoev.ru     nxt_runtime_thread_pool_destroy(task, rt, rt->start);
34820Sigor@sysoev.ru 
34920Sigor@sysoev.ru     return;
35020Sigor@sysoev.ru 
35120Sigor@sysoev.ru fail:
35220Sigor@sysoev.ru 
353697Sigor@sysoev.ru     nxt_runtime_quit(task, 1);
35420Sigor@sysoev.ru }
35520Sigor@sysoev.ru 
35620Sigor@sysoev.ru 
35720Sigor@sysoev.ru static void
358697Sigor@sysoev.ru nxt_runtime_initial_start(nxt_task_t *task, nxt_uint_t status)
35920Sigor@sysoev.ru {
36020Sigor@sysoev.ru     nxt_int_t                    ret;
36120Sigor@sysoev.ru     nxt_thread_t                 *thr;
36220Sigor@sysoev.ru     nxt_runtime_t                *rt;
36320Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
36420Sigor@sysoev.ru 
36520Sigor@sysoev.ru     thr = task->thread;
36620Sigor@sysoev.ru     rt = thr->runtime;
36720Sigor@sysoev.ru 
36820Sigor@sysoev.ru     if (rt->inherited_sockets == NULL && rt->daemon) {
36920Sigor@sysoev.ru 
37020Sigor@sysoev.ru         if (nxt_process_daemon(task) != NXT_OK) {
37120Sigor@sysoev.ru             goto fail;
37220Sigor@sysoev.ru         }
37320Sigor@sysoev.ru 
37420Sigor@sysoev.ru         /*
37520Sigor@sysoev.ru          * An event engine should be updated after fork()
37620Sigor@sysoev.ru          * even if an event facility was not changed because:
37720Sigor@sysoev.ru          * 1) inherited kqueue descriptor is invalid,
37820Sigor@sysoev.ru          * 2) the signal thread is not inherited.
37920Sigor@sysoev.ru          */
38020Sigor@sysoev.ru         interface = nxt_service_get(rt->services, "engine", rt->engine);
38120Sigor@sysoev.ru         if (interface == NULL) {
38220Sigor@sysoev.ru             goto fail;
38320Sigor@sysoev.ru         }
38420Sigor@sysoev.ru 
38520Sigor@sysoev.ru         ret = nxt_event_engine_change(task->thread->engine, interface,
38620Sigor@sysoev.ru                                       rt->batch);
38720Sigor@sysoev.ru         if (ret != NXT_OK) {
38820Sigor@sysoev.ru             goto fail;
38920Sigor@sysoev.ru         }
39020Sigor@sysoev.ru     }
39120Sigor@sysoev.ru 
39220Sigor@sysoev.ru     ret = nxt_runtime_pid_file_create(task, rt->pid_file);
39320Sigor@sysoev.ru     if (ret != NXT_OK) {
39420Sigor@sysoev.ru         goto fail;
39520Sigor@sysoev.ru     }
39620Sigor@sysoev.ru 
39720Sigor@sysoev.ru     if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) {
39820Sigor@sysoev.ru         goto fail;
39920Sigor@sysoev.ru     }
40020Sigor@sysoev.ru 
40120Sigor@sysoev.ru     thr->engine->max_connections = rt->engine_connections;
40220Sigor@sysoev.ru 
403695Sigor@sysoev.ru     if (nxt_main_process_start(thr, task, rt) != NXT_ERROR) {
40420Sigor@sysoev.ru         return;
40520Sigor@sysoev.ru     }
40620Sigor@sysoev.ru 
40720Sigor@sysoev.ru fail:
40820Sigor@sysoev.ru 
409697Sigor@sysoev.ru     nxt_runtime_quit(task, 1);
41020Sigor@sysoev.ru }
41120Sigor@sysoev.ru 
41220Sigor@sysoev.ru 
41320Sigor@sysoev.ru void
414697Sigor@sysoev.ru nxt_runtime_quit(nxt_task_t *task, nxt_uint_t status)
41520Sigor@sysoev.ru {
41620Sigor@sysoev.ru     nxt_bool_t          done;
41720Sigor@sysoev.ru     nxt_runtime_t       *rt;
41820Sigor@sysoev.ru     nxt_event_engine_t  *engine;
41920Sigor@sysoev.ru 
42020Sigor@sysoev.ru     rt = task->thread->runtime;
421697Sigor@sysoev.ru     rt->status |= status;
42220Sigor@sysoev.ru     engine = task->thread->engine;
42320Sigor@sysoev.ru 
42420Sigor@sysoev.ru     nxt_debug(task, "exiting");
42520Sigor@sysoev.ru 
42620Sigor@sysoev.ru     done = 1;
42720Sigor@sysoev.ru 
42820Sigor@sysoev.ru     if (!engine->shutdown) {
42920Sigor@sysoev.ru         engine->shutdown = 1;
43020Sigor@sysoev.ru 
43120Sigor@sysoev.ru         if (!nxt_array_is_empty(rt->thread_pools)) {
43220Sigor@sysoev.ru             nxt_runtime_thread_pool_destroy(task, rt, nxt_runtime_quit);
43320Sigor@sysoev.ru             done = 0;
43420Sigor@sysoev.ru         }
43520Sigor@sysoev.ru 
436696Sigor@sysoev.ru         if (rt->type == NXT_PROCESS_MAIN) {
437754Smax.romanov@nginx.com             nxt_main_stop_all_processes(task, rt);
43820Sigor@sysoev.ru             done = 0;
43920Sigor@sysoev.ru         }
44020Sigor@sysoev.ru     }
44120Sigor@sysoev.ru 
44220Sigor@sysoev.ru     nxt_runtime_close_idle_connections(engine);
44320Sigor@sysoev.ru 
44420Sigor@sysoev.ru     if (done) {
44520Sigor@sysoev.ru         nxt_work_queue_add(&engine->fast_work_queue, nxt_runtime_exit,
44620Sigor@sysoev.ru                            task, rt, engine);
44720Sigor@sysoev.ru     }
44820Sigor@sysoev.ru }
44920Sigor@sysoev.ru 
45020Sigor@sysoev.ru 
45120Sigor@sysoev.ru static void
45220Sigor@sysoev.ru nxt_runtime_close_idle_connections(nxt_event_engine_t *engine)
45320Sigor@sysoev.ru {
45462Sigor@sysoev.ru     nxt_conn_t        *c;
45520Sigor@sysoev.ru     nxt_queue_t       *idle;
45620Sigor@sysoev.ru     nxt_queue_link_t  *link, *next;
45720Sigor@sysoev.ru 
45820Sigor@sysoev.ru     nxt_debug(&engine->task, "close idle connections");
45920Sigor@sysoev.ru 
46020Sigor@sysoev.ru     idle = &engine->idle_connections;
46120Sigor@sysoev.ru 
46220Sigor@sysoev.ru     for (link = nxt_queue_head(idle);
46320Sigor@sysoev.ru          link != nxt_queue_tail(idle);
46420Sigor@sysoev.ru          link = next)
46520Sigor@sysoev.ru     {
46620Sigor@sysoev.ru         next = nxt_queue_next(link);
46762Sigor@sysoev.ru         c = nxt_queue_link_data(link, nxt_conn_t, link);
46820Sigor@sysoev.ru 
46920Sigor@sysoev.ru         if (!c->socket.read_ready) {
47020Sigor@sysoev.ru             nxt_queue_remove(link);
47162Sigor@sysoev.ru             nxt_conn_close(engine, c);
47220Sigor@sysoev.ru         }
47320Sigor@sysoev.ru     }
47420Sigor@sysoev.ru }
47520Sigor@sysoev.ru 
47620Sigor@sysoev.ru 
47720Sigor@sysoev.ru static void
47820Sigor@sysoev.ru nxt_runtime_exit(nxt_task_t *task, void *obj, void *data)
47920Sigor@sysoev.ru {
480697Sigor@sysoev.ru     int                 status;
481125Smax.romanov@nginx.com     nxt_runtime_t       *rt;
482125Smax.romanov@nginx.com     nxt_process_t       *process;
48320Sigor@sysoev.ru     nxt_event_engine_t  *engine;
48420Sigor@sysoev.ru 
48520Sigor@sysoev.ru     rt = obj;
48620Sigor@sysoev.ru     engine = data;
48720Sigor@sysoev.ru 
48820Sigor@sysoev.ru     nxt_debug(task, "thread pools: %d", rt->thread_pools->nelts);
48920Sigor@sysoev.ru 
49020Sigor@sysoev.ru     if (!nxt_array_is_empty(rt->thread_pools)) {
49120Sigor@sysoev.ru         return;
49220Sigor@sysoev.ru     }
49320Sigor@sysoev.ru 
494696Sigor@sysoev.ru     if (rt->type == NXT_PROCESS_MAIN) {
49520Sigor@sysoev.ru         if (rt->pid_file != NULL) {
49620Sigor@sysoev.ru             nxt_file_delete(rt->pid_file);
49720Sigor@sysoev.ru         }
498234Sigor@sysoev.ru 
499234Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
500234Sigor@sysoev.ru         {
501234Sigor@sysoev.ru             nxt_sockaddr_t   *sa;
502234Sigor@sysoev.ru             nxt_file_name_t  *name;
503234Sigor@sysoev.ru 
504234Sigor@sysoev.ru             sa = rt->controller_listen;
505234Sigor@sysoev.ru 
506234Sigor@sysoev.ru             if (sa->u.sockaddr.sa_family == AF_UNIX) {
507234Sigor@sysoev.ru                 name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path;
508234Sigor@sysoev.ru                 (void) nxt_file_delete(name);
509234Sigor@sysoev.ru             }
510234Sigor@sysoev.ru         }
511234Sigor@sysoev.ru #endif
51220Sigor@sysoev.ru     }
51320Sigor@sysoev.ru 
51420Sigor@sysoev.ru     if (!engine->event.signal_support) {
51520Sigor@sysoev.ru         nxt_event_engine_signals_stop(engine);
51620Sigor@sysoev.ru     }
51720Sigor@sysoev.ru 
518125Smax.romanov@nginx.com     nxt_runtime_process_each(rt, process) {
519125Smax.romanov@nginx.com 
520349Smax.romanov@nginx.com         nxt_process_close_ports(task, process);
521125Smax.romanov@nginx.com 
522125Smax.romanov@nginx.com     } nxt_runtime_process_loop;
523125Smax.romanov@nginx.com 
524196Smax.romanov@nginx.com     nxt_thread_mutex_destroy(&rt->processes_mutex);
525196Smax.romanov@nginx.com 
526697Sigor@sysoev.ru     status = rt->status;
527125Smax.romanov@nginx.com     nxt_mp_destroy(rt->mem_pool);
528125Smax.romanov@nginx.com 
529697Sigor@sysoev.ru     nxt_debug(task, "exit: %d", status);
53020Sigor@sysoev.ru 
531697Sigor@sysoev.ru     exit(status);
53220Sigor@sysoev.ru     nxt_unreachable();
53320Sigor@sysoev.ru }
53420Sigor@sysoev.ru 
53520Sigor@sysoev.ru 
53620Sigor@sysoev.ru static nxt_int_t
53720Sigor@sysoev.ru nxt_runtime_event_engine_change(nxt_task_t *task, nxt_runtime_t *rt)
53820Sigor@sysoev.ru {
53920Sigor@sysoev.ru     nxt_event_engine_t           *engine;
54020Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
54120Sigor@sysoev.ru 
54220Sigor@sysoev.ru     engine = task->thread->engine;
54320Sigor@sysoev.ru 
54420Sigor@sysoev.ru     if (engine->batch == rt->batch
54520Sigor@sysoev.ru         && nxt_strcmp(engine->event.name, rt->engine) == 0)
54620Sigor@sysoev.ru     {
54720Sigor@sysoev.ru         return NXT_OK;
54820Sigor@sysoev.ru     }
54920Sigor@sysoev.ru 
55020Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", rt->engine);
55120Sigor@sysoev.ru 
55220Sigor@sysoev.ru     if (interface != NULL) {
55320Sigor@sysoev.ru         return nxt_event_engine_change(engine, interface, rt->batch);
55420Sigor@sysoev.ru     }
55520Sigor@sysoev.ru 
55620Sigor@sysoev.ru     return NXT_ERROR;
55720Sigor@sysoev.ru }
55820Sigor@sysoev.ru 
55920Sigor@sysoev.ru 
56020Sigor@sysoev.ru void
56120Sigor@sysoev.ru nxt_runtime_event_engine_free(nxt_runtime_t *rt)
56220Sigor@sysoev.ru {
56353Sigor@sysoev.ru     nxt_queue_link_t    *link;
56453Sigor@sysoev.ru     nxt_event_engine_t  *engine;
56520Sigor@sysoev.ru 
56653Sigor@sysoev.ru     link = nxt_queue_first(&rt->engines);
56753Sigor@sysoev.ru     nxt_queue_remove(link);
56820Sigor@sysoev.ru 
56953Sigor@sysoev.ru     engine = nxt_queue_link_data(link, nxt_event_engine_t, link);
57020Sigor@sysoev.ru     nxt_event_engine_free(engine);
57120Sigor@sysoev.ru }
57220Sigor@sysoev.ru 
57320Sigor@sysoev.ru 
57420Sigor@sysoev.ru nxt_int_t
57520Sigor@sysoev.ru nxt_runtime_thread_pool_create(nxt_thread_t *thr, nxt_runtime_t *rt,
57620Sigor@sysoev.ru     nxt_uint_t max_threads, nxt_nsec_t timeout)
57720Sigor@sysoev.ru {
57820Sigor@sysoev.ru     nxt_thread_pool_t   *thread_pool, **tp;
57920Sigor@sysoev.ru 
58020Sigor@sysoev.ru     tp = nxt_array_add(rt->thread_pools);
58120Sigor@sysoev.ru     if (tp == NULL) {
58220Sigor@sysoev.ru         return NXT_ERROR;
58320Sigor@sysoev.ru     }
58420Sigor@sysoev.ru 
58520Sigor@sysoev.ru     thread_pool = nxt_thread_pool_create(max_threads, timeout,
58620Sigor@sysoev.ru                                          nxt_runtime_thread_pool_init,
58720Sigor@sysoev.ru                                          thr->engine,
58820Sigor@sysoev.ru                                          nxt_runtime_thread_pool_exit);
58920Sigor@sysoev.ru 
59020Sigor@sysoev.ru     if (nxt_fast_path(thread_pool != NULL)) {
59120Sigor@sysoev.ru         *tp = thread_pool;
59220Sigor@sysoev.ru     }
59320Sigor@sysoev.ru 
59420Sigor@sysoev.ru     return NXT_OK;
59520Sigor@sysoev.ru }
59620Sigor@sysoev.ru 
59720Sigor@sysoev.ru 
59820Sigor@sysoev.ru static void
59920Sigor@sysoev.ru nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt,
60020Sigor@sysoev.ru     nxt_runtime_cont_t cont)
60120Sigor@sysoev.ru {
60220Sigor@sysoev.ru     nxt_uint_t         n;
60320Sigor@sysoev.ru     nxt_thread_pool_t  **tp;
60420Sigor@sysoev.ru 
60520Sigor@sysoev.ru     rt->continuation = cont;
60620Sigor@sysoev.ru 
60720Sigor@sysoev.ru     n = rt->thread_pools->nelts;
60820Sigor@sysoev.ru 
60920Sigor@sysoev.ru     if (n == 0) {
610697Sigor@sysoev.ru         cont(task, 0);
61120Sigor@sysoev.ru         return;
61220Sigor@sysoev.ru     }
61320Sigor@sysoev.ru 
61420Sigor@sysoev.ru     tp = rt->thread_pools->elts;
61520Sigor@sysoev.ru 
61620Sigor@sysoev.ru     do {
61720Sigor@sysoev.ru         nxt_thread_pool_destroy(*tp);
61820Sigor@sysoev.ru 
61920Sigor@sysoev.ru         tp++;
62020Sigor@sysoev.ru         n--;
62120Sigor@sysoev.ru     } while (n != 0);
62220Sigor@sysoev.ru }
62320Sigor@sysoev.ru 
62420Sigor@sysoev.ru 
62520Sigor@sysoev.ru static void
62620Sigor@sysoev.ru nxt_runtime_thread_pool_init(void)
62720Sigor@sysoev.ru {
62820Sigor@sysoev.ru #if (NXT_REGEX)
62920Sigor@sysoev.ru     nxt_regex_init(0);
63020Sigor@sysoev.ru #endif
63120Sigor@sysoev.ru }
63220Sigor@sysoev.ru 
63320Sigor@sysoev.ru 
63420Sigor@sysoev.ru static void
63520Sigor@sysoev.ru nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj, void *data)
63620Sigor@sysoev.ru {
63720Sigor@sysoev.ru     nxt_uint_t           i, n;
63820Sigor@sysoev.ru     nxt_runtime_t        *rt;
63920Sigor@sysoev.ru     nxt_thread_pool_t    *tp, **thread_pools;
64020Sigor@sysoev.ru     nxt_thread_handle_t  handle;
64120Sigor@sysoev.ru 
64220Sigor@sysoev.ru     tp = obj;
64320Sigor@sysoev.ru 
64420Sigor@sysoev.ru     if (data != NULL) {
64520Sigor@sysoev.ru         handle = (nxt_thread_handle_t) (uintptr_t) data;
64620Sigor@sysoev.ru         nxt_thread_wait(handle);
64720Sigor@sysoev.ru     }
64820Sigor@sysoev.ru 
64920Sigor@sysoev.ru     rt = task->thread->runtime;
65020Sigor@sysoev.ru 
65120Sigor@sysoev.ru     thread_pools = rt->thread_pools->elts;
65220Sigor@sysoev.ru     n = rt->thread_pools->nelts;
65320Sigor@sysoev.ru 
65420Sigor@sysoev.ru     nxt_debug(task, "thread pools: %ui", n);
65520Sigor@sysoev.ru 
65620Sigor@sysoev.ru     for (i = 0; i < n; i++) {
65720Sigor@sysoev.ru 
65820Sigor@sysoev.ru         if (tp == thread_pools[i]) {
65920Sigor@sysoev.ru             nxt_array_remove(rt->thread_pools, &thread_pools[i]);
66020Sigor@sysoev.ru 
66120Sigor@sysoev.ru             if (n == 1) {
66220Sigor@sysoev.ru                 /* The last thread pool. */
663697Sigor@sysoev.ru                 rt->continuation(task, 0);
66420Sigor@sysoev.ru             }
66520Sigor@sysoev.ru 
66620Sigor@sysoev.ru             return;
66720Sigor@sysoev.ru         }
66820Sigor@sysoev.ru     }
66920Sigor@sysoev.ru }
67020Sigor@sysoev.ru 
67120Sigor@sysoev.ru 
67220Sigor@sysoev.ru static nxt_int_t
67320Sigor@sysoev.ru nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt)
67420Sigor@sysoev.ru {
67520Sigor@sysoev.ru     nxt_int_t                    ret;
676251Sigor@sysoev.ru     nxt_str_t                    control;
677251Sigor@sysoev.ru     nxt_uint_t                   n;
67820Sigor@sysoev.ru     nxt_file_t                   *file;
679251Sigor@sysoev.ru     const char                   *slash;
680234Sigor@sysoev.ru     nxt_sockaddr_t               *sa;
68120Sigor@sysoev.ru     nxt_file_name_str_t          file_name;
68220Sigor@sysoev.ru     const nxt_event_interface_t  *interface;
68320Sigor@sysoev.ru 
68420Sigor@sysoev.ru     rt->daemon = 1;
68520Sigor@sysoev.ru     rt->engine_connections = 256;
68620Sigor@sysoev.ru     rt->auxiliary_threads = 2;
687232Sigor@sysoev.ru     rt->user_cred.user = NXT_USER;
688232Sigor@sysoev.ru     rt->group = NXT_GROUP;
689231Sigor@sysoev.ru     rt->pid = NXT_PID;
690230Sigor@sysoev.ru     rt->log = NXT_LOG;
691233Sigor@sysoev.ru     rt->modules = NXT_MODULES;
692314Svbart@nginx.com     rt->state = NXT_STATE;
693234Sigor@sysoev.ru     rt->control = NXT_CONTROL_SOCK;
69420Sigor@sysoev.ru 
695*1182St.nateldemoura@f5.com     nxt_memzero(&rt->capabilities, sizeof(nxt_capabilities_t));
696*1182St.nateldemoura@f5.com 
69720Sigor@sysoev.ru     if (nxt_runtime_conf_read_cmd(task, rt) != NXT_OK) {
69820Sigor@sysoev.ru         return NXT_ERROR;
69920Sigor@sysoev.ru     }
70020Sigor@sysoev.ru 
701*1182St.nateldemoura@f5.com     if (nxt_capability_set(task, &rt->capabilities) != NXT_OK) {
70220Sigor@sysoev.ru         return NXT_ERROR;
70320Sigor@sysoev.ru     }
70420Sigor@sysoev.ru 
705*1182St.nateldemoura@f5.com     if (rt->capabilities.setid) {
706*1182St.nateldemoura@f5.com         if (nxt_user_cred_get(task, &rt->user_cred, rt->group) != NXT_OK) {
707*1182St.nateldemoura@f5.com             return NXT_ERROR;
708*1182St.nateldemoura@f5.com         }
709*1182St.nateldemoura@f5.com 
710*1182St.nateldemoura@f5.com     } else {
711*1182St.nateldemoura@f5.com         nxt_log(task, NXT_LOG_WARN, "Unit is running unprivileged, then it "
712*1182St.nateldemoura@f5.com                 "cannot use arbitrary user and group.");
713*1182St.nateldemoura@f5.com     }
714*1182St.nateldemoura@f5.com 
71520Sigor@sysoev.ru     /* An engine's parameters. */
71620Sigor@sysoev.ru 
71720Sigor@sysoev.ru     interface = nxt_service_get(rt->services, "engine", rt->engine);
71820Sigor@sysoev.ru     if (interface == NULL) {
71920Sigor@sysoev.ru         return NXT_ERROR;
72020Sigor@sysoev.ru     }
72120Sigor@sysoev.ru 
72220Sigor@sysoev.ru     rt->engine = interface->name;
72320Sigor@sysoev.ru 
724252Smax.romanov@nginx.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->pid);
72520Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
72620Sigor@sysoev.ru         return NXT_ERROR;
72720Sigor@sysoev.ru     }
72820Sigor@sysoev.ru 
72920Sigor@sysoev.ru     rt->pid_file = file_name.start;
73020Sigor@sysoev.ru 
731230Sigor@sysoev.ru     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->log);
73220Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
73320Sigor@sysoev.ru         return NXT_ERROR;
73420Sigor@sysoev.ru     }
73520Sigor@sysoev.ru 
73620Sigor@sysoev.ru     file = nxt_list_first(rt->log_files);
73720Sigor@sysoev.ru     file->name = file_name.start;
73820Sigor@sysoev.ru 
739251Sigor@sysoev.ru     slash = "";
740251Sigor@sysoev.ru     n = nxt_strlen(rt->modules);
741251Sigor@sysoev.ru 
742251Sigor@sysoev.ru     if (n > 1 && rt->modules[n - 1] != '/') {
743251Sigor@sysoev.ru         slash = "/";
744251Sigor@sysoev.ru     }
745251Sigor@sysoev.ru 
746260Sigor@sysoev.ru     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%s*.unit.so%Z",
747251Sigor@sysoev.ru                                rt->modules, slash);
748233Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
749233Sigor@sysoev.ru         return NXT_ERROR;
750233Sigor@sysoev.ru     }
751233Sigor@sysoev.ru 
752233Sigor@sysoev.ru     rt->modules = (char *) file_name.start;
753233Sigor@sysoev.ru 
754314Svbart@nginx.com     slash = "";
755314Svbart@nginx.com     n = nxt_strlen(rt->state);
756314Svbart@nginx.com 
757314Svbart@nginx.com     if (n > 1 && rt->state[n - 1] != '/') {
758314Svbart@nginx.com         slash = "/";
759314Svbart@nginx.com     }
760314Svbart@nginx.com 
761314Svbart@nginx.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sconf.json%Z",
762314Svbart@nginx.com                                rt->state, slash);
763314Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
764314Svbart@nginx.com         return NXT_ERROR;
765314Svbart@nginx.com     }
766314Svbart@nginx.com 
767314Svbart@nginx.com     rt->conf = (char *) file_name.start;
768314Svbart@nginx.com 
769314Svbart@nginx.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s.tmp%Z", rt->conf);
770314Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
771314Svbart@nginx.com         return NXT_ERROR;
772314Svbart@nginx.com     }
773314Svbart@nginx.com 
774314Svbart@nginx.com     rt->conf_tmp = (char *) file_name.start;
775314Svbart@nginx.com 
776774Svbart@nginx.com     ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%scerts/%Z",
777774Svbart@nginx.com                                rt->state, slash);
778774Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
779774Svbart@nginx.com         return NXT_ERROR;
780774Svbart@nginx.com     }
781774Svbart@nginx.com 
782774Svbart@nginx.com     ret = mkdir((char *) file_name.start, S_IRWXU);
783774Svbart@nginx.com 
784774Svbart@nginx.com     if (nxt_fast_path(ret == 0 || nxt_errno == EEXIST)) {
785774Svbart@nginx.com         rt->certs.length = file_name.len;
786774Svbart@nginx.com         rt->certs.start = file_name.start;
787774Svbart@nginx.com 
788774Svbart@nginx.com     } else {
789774Svbart@nginx.com         nxt_alert(task, "Unable to create certificates storage directory: "
790774Svbart@nginx.com                   "mkdir(%s) failed %E", file_name.start, nxt_errno);
791774Svbart@nginx.com     }
792774Svbart@nginx.com 
793234Sigor@sysoev.ru     control.length = nxt_strlen(rt->control);
794234Sigor@sysoev.ru     control.start = (u_char *) rt->control;
795234Sigor@sysoev.ru 
796649Svbart@nginx.com     sa = nxt_sockaddr_parse(rt->mem_pool, &control);
797234Sigor@sysoev.ru     if (nxt_slow_path(sa == NULL)) {
798234Sigor@sysoev.ru         return NXT_ERROR;
799234Sigor@sysoev.ru     }
800234Sigor@sysoev.ru 
801649Svbart@nginx.com     sa->type = SOCK_STREAM;
802649Svbart@nginx.com 
803234Sigor@sysoev.ru     rt->controller_listen = sa;
804234Sigor@sysoev.ru 
805234Sigor@sysoev.ru     if (nxt_runtime_controller_socket(task, rt) != NXT_OK) {
806234Sigor@sysoev.ru         return NXT_ERROR;
807234Sigor@sysoev.ru     }
808234Sigor@sysoev.ru 
80920Sigor@sysoev.ru     return NXT_OK;
81020Sigor@sysoev.ru }
81120Sigor@sysoev.ru 
81220Sigor@sysoev.ru 
81320Sigor@sysoev.ru static nxt_int_t
81420Sigor@sysoev.ru nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt)
81520Sigor@sysoev.ru {
816234Sigor@sysoev.ru     char    *p, **argv;
817234Sigor@sysoev.ru     u_char  *end;
818234Sigor@sysoev.ru     u_char  buf[1024];
81920Sigor@sysoev.ru 
820226Svbart@nginx.com     static const char  version[] =
821259Sigor@sysoev.ru         "unit version: " NXT_VERSION "\n"
822221Sigor@sysoev.ru         "configured as ./configure" NXT_CONFIGURE_OPTIONS "\n";
823221Sigor@sysoev.ru 
824234Sigor@sysoev.ru     static const char  no_control[] =
825234Sigor@sysoev.ru                        "option \"--control\" requires socket address\n";
826232Sigor@sysoev.ru     static const char  no_user[] = "option \"--user\" requires username\n";
827232Sigor@sysoev.ru     static const char  no_group[] = "option \"--group\" requires group name\n";
828231Sigor@sysoev.ru     static const char  no_pid[] = "option \"--pid\" requires filename\n";
829230Sigor@sysoev.ru     static const char  no_log[] = "option \"--log\" requires filename\n";
830233Sigor@sysoev.ru     static const char  no_modules[] =
831233Sigor@sysoev.ru                        "option \"--modules\" requires directory\n";
832314Svbart@nginx.com     static const char  no_state[] = "option \"--state\" requires directory\n";
833230Sigor@sysoev.ru 
834235Sigor@sysoev.ru     static const char  help[] =
835235Sigor@sysoev.ru         "\n"
836259Sigor@sysoev.ru         "unit options:\n"
837235Sigor@sysoev.ru         "\n"
838259Sigor@sysoev.ru         "  --version            print unit version and configure options\n"
839235Sigor@sysoev.ru         "\n"
840259Sigor@sysoev.ru         "  --no-daemon          run unit in non-daemon mode\n"
841235Sigor@sysoev.ru         "\n"
842235Sigor@sysoev.ru         "  --control ADDRESS    set address of control API socket\n"
843235Sigor@sysoev.ru         "                       default: \"" NXT_CONTROL_SOCK "\"\n"
844235Sigor@sysoev.ru         "\n"
845239Sigor@sysoev.ru         "  --pid FILE           set pid filename\n"
846235Sigor@sysoev.ru         "                       default: \"" NXT_PID "\"\n"
847235Sigor@sysoev.ru         "\n"
848239Sigor@sysoev.ru         "  --log FILE           set log filename\n"
849235Sigor@sysoev.ru         "                       default: \"" NXT_LOG "\"\n"
850235Sigor@sysoev.ru         "\n"
851239Sigor@sysoev.ru         "  --modules DIRECTORY  set modules directory name\n"
852235Sigor@sysoev.ru         "                       default: \"" NXT_MODULES "\"\n"
853235Sigor@sysoev.ru         "\n"
854314Svbart@nginx.com         "  --state DIRECTORY    set state directory name\n"
855314Svbart@nginx.com         "                       default: \"" NXT_STATE "\"\n"
856314Svbart@nginx.com         "\n"
857235Sigor@sysoev.ru         "  --user USER          set non-privileged processes to run"
858235Sigor@sysoev.ru                                 " as specified user\n"
859235Sigor@sysoev.ru         "                       default: \"" NXT_USER "\"\n"
860235Sigor@sysoev.ru         "\n"
861235Sigor@sysoev.ru         "  --group GROUP        set non-privileged processes to run"
862235Sigor@sysoev.ru                                 " as specified group\n"
863235Sigor@sysoev.ru         "                       default: ";
864235Sigor@sysoev.ru 
865235Sigor@sysoev.ru     static const char  group[] = "\"" NXT_GROUP "\"\n\n";
866235Sigor@sysoev.ru     static const char  primary[] = "user's primary group\n\n";
867235Sigor@sysoev.ru 
868222Sigor@sysoev.ru     argv = &nxt_process_argv[1];
86920Sigor@sysoev.ru 
87020Sigor@sysoev.ru     while (*argv != NULL) {
87120Sigor@sysoev.ru         p = *argv++;
87220Sigor@sysoev.ru 
873234Sigor@sysoev.ru         if (nxt_strcmp(p, "--control") == 0) {
87420Sigor@sysoev.ru             if (*argv == NULL) {
875703Svbart@nginx.com                 write(STDERR_FILENO, no_control, nxt_length(no_control));
87620Sigor@sysoev.ru                 return NXT_ERROR;
87720Sigor@sysoev.ru             }
87820Sigor@sysoev.ru 
87920Sigor@sysoev.ru             p = *argv++;
88020Sigor@sysoev.ru 
881234Sigor@sysoev.ru             rt->control = p;
88220Sigor@sysoev.ru 
88320Sigor@sysoev.ru             continue;
88420Sigor@sysoev.ru         }
88520Sigor@sysoev.ru 
88620Sigor@sysoev.ru         if (nxt_strcmp(p, "--user") == 0) {
88720Sigor@sysoev.ru             if (*argv == NULL) {
888703Svbart@nginx.com                 write(STDERR_FILENO, no_user, nxt_length(no_user));
88920Sigor@sysoev.ru                 return NXT_ERROR;
89020Sigor@sysoev.ru             }
89120Sigor@sysoev.ru 
89220Sigor@sysoev.ru             p = *argv++;
89320Sigor@sysoev.ru 
89420Sigor@sysoev.ru             rt->user_cred.user = p;
89520Sigor@sysoev.ru 
89620Sigor@sysoev.ru             continue;
89720Sigor@sysoev.ru         }
89820Sigor@sysoev.ru 
89920Sigor@sysoev.ru         if (nxt_strcmp(p, "--group") == 0) {
90020Sigor@sysoev.ru             if (*argv == NULL) {
901703Svbart@nginx.com                 write(STDERR_FILENO, no_group, nxt_length(no_group));
90220Sigor@sysoev.ru                 return NXT_ERROR;
90320Sigor@sysoev.ru             }
90420Sigor@sysoev.ru 
90520Sigor@sysoev.ru             p = *argv++;
90620Sigor@sysoev.ru 
90720Sigor@sysoev.ru             rt->group = p;
90820Sigor@sysoev.ru 
90920Sigor@sysoev.ru             continue;
91020Sigor@sysoev.ru         }
91120Sigor@sysoev.ru 
91220Sigor@sysoev.ru         if (nxt_strcmp(p, "--pid") == 0) {
91320Sigor@sysoev.ru             if (*argv == NULL) {
914703Svbart@nginx.com                 write(STDERR_FILENO, no_pid, nxt_length(no_pid));
91520Sigor@sysoev.ru                 return NXT_ERROR;
91620Sigor@sysoev.ru             }
91720Sigor@sysoev.ru 
91820Sigor@sysoev.ru             p = *argv++;
91920Sigor@sysoev.ru 
92020Sigor@sysoev.ru             rt->pid = p;
92120Sigor@sysoev.ru 
92220Sigor@sysoev.ru             continue;
92320Sigor@sysoev.ru         }
92420Sigor@sysoev.ru 
92520Sigor@sysoev.ru         if (nxt_strcmp(p, "--log") == 0) {
92620Sigor@sysoev.ru             if (*argv == NULL) {
927703Svbart@nginx.com                 write(STDERR_FILENO, no_log, nxt_length(no_log));
92820Sigor@sysoev.ru                 return NXT_ERROR;
92920Sigor@sysoev.ru             }
93020Sigor@sysoev.ru 
93120Sigor@sysoev.ru             p = *argv++;
93220Sigor@sysoev.ru 
933230Sigor@sysoev.ru             rt->log = p;
93420Sigor@sysoev.ru 
93520Sigor@sysoev.ru             continue;
93620Sigor@sysoev.ru         }
93720Sigor@sysoev.ru 
938233Sigor@sysoev.ru         if (nxt_strcmp(p, "--modules") == 0) {
939233Sigor@sysoev.ru             if (*argv == NULL) {
940703Svbart@nginx.com                 write(STDERR_FILENO, no_modules, nxt_length(no_modules));
941233Sigor@sysoev.ru                 return NXT_ERROR;
942233Sigor@sysoev.ru             }
943233Sigor@sysoev.ru 
944233Sigor@sysoev.ru             p = *argv++;
945233Sigor@sysoev.ru 
946233Sigor@sysoev.ru             rt->modules = p;
947233Sigor@sysoev.ru 
948233Sigor@sysoev.ru             continue;
949233Sigor@sysoev.ru         }
950233Sigor@sysoev.ru 
951314Svbart@nginx.com         if (nxt_strcmp(p, "--state") == 0) {
952314Svbart@nginx.com             if (*argv == NULL) {
953703Svbart@nginx.com                 write(STDERR_FILENO, no_state, nxt_length(no_state));
954314Svbart@nginx.com                 return NXT_ERROR;
955314Svbart@nginx.com             }
956314Svbart@nginx.com 
957314Svbart@nginx.com             p = *argv++;
958314Svbart@nginx.com 
959314Svbart@nginx.com             rt->state = p;
960314Svbart@nginx.com 
961314Svbart@nginx.com             continue;
962314Svbart@nginx.com         }
963314Svbart@nginx.com 
964219Sigor@sysoev.ru         if (nxt_strcmp(p, "--no-daemon") == 0) {
96520Sigor@sysoev.ru             rt->daemon = 0;
96620Sigor@sysoev.ru             continue;
96720Sigor@sysoev.ru         }
968221Sigor@sysoev.ru 
969221Sigor@sysoev.ru         if (nxt_strcmp(p, "--version") == 0) {
970703Svbart@nginx.com             write(STDERR_FILENO, version, nxt_length(version));
971221Sigor@sysoev.ru             exit(0);
972221Sigor@sysoev.ru         }
973222Sigor@sysoev.ru 
974643Svbart@nginx.com         if (nxt_strcmp(p, "--help") == 0 || nxt_strcmp(p, "-h") == 0) {
975703Svbart@nginx.com             write(STDOUT_FILENO, help, nxt_length(help));
976235Sigor@sysoev.ru 
977235Sigor@sysoev.ru             if (sizeof(NXT_GROUP) == 1) {
978703Svbart@nginx.com                 write(STDOUT_FILENO, primary, nxt_length(primary));
979235Sigor@sysoev.ru 
980235Sigor@sysoev.ru             } else {
981703Svbart@nginx.com                 write(STDOUT_FILENO, group, nxt_length(group));
982235Sigor@sysoev.ru             }
983235Sigor@sysoev.ru 
984235Sigor@sysoev.ru             exit(0);
985235Sigor@sysoev.ru         }
986235Sigor@sysoev.ru 
987643Svbart@nginx.com         end = nxt_sprintf(buf, buf + sizeof(buf), "unknown option \"%s\", "
988643Svbart@nginx.com                           "try \"%s -h\" for available options\n",
989643Svbart@nginx.com                           p, nxt_process_argv[0]);
990643Svbart@nginx.com 
991222Sigor@sysoev.ru         write(STDERR_FILENO, buf, end - buf);
992222Sigor@sysoev.ru 
993222Sigor@sysoev.ru         return NXT_ERROR;
99420Sigor@sysoev.ru     }
99520Sigor@sysoev.ru 
99620Sigor@sysoev.ru     return NXT_OK;
99720Sigor@sysoev.ru }
99820Sigor@sysoev.ru 
99920Sigor@sysoev.ru 
100020Sigor@sysoev.ru nxt_listen_socket_t *
100120Sigor@sysoev.ru nxt_runtime_listen_socket_add(nxt_runtime_t *rt, nxt_sockaddr_t *sa)
100220Sigor@sysoev.ru {
100365Sigor@sysoev.ru     nxt_mp_t             *mp;
100420Sigor@sysoev.ru     nxt_listen_socket_t  *ls;
100520Sigor@sysoev.ru 
100620Sigor@sysoev.ru     ls = nxt_array_zero_add(rt->listen_sockets);
100720Sigor@sysoev.ru     if (ls == NULL) {
100820Sigor@sysoev.ru         return NULL;
100920Sigor@sysoev.ru     }
101020Sigor@sysoev.ru 
101120Sigor@sysoev.ru     mp = rt->mem_pool;
101220Sigor@sysoev.ru 
101320Sigor@sysoev.ru     ls->sockaddr = nxt_sockaddr_create(mp, &sa->u.sockaddr, sa->socklen,
101420Sigor@sysoev.ru                                        sa->length);
101520Sigor@sysoev.ru     if (ls->sockaddr == NULL) {
101620Sigor@sysoev.ru         return NULL;
101720Sigor@sysoev.ru     }
101820Sigor@sysoev.ru 
101920Sigor@sysoev.ru     ls->sockaddr->type = sa->type;
102020Sigor@sysoev.ru 
102120Sigor@sysoev.ru     nxt_sockaddr_text(ls->sockaddr);
102220Sigor@sysoev.ru 
102320Sigor@sysoev.ru     ls->socket = -1;
102420Sigor@sysoev.ru     ls->backlog = NXT_LISTEN_BACKLOG;
102520Sigor@sysoev.ru 
102620Sigor@sysoev.ru     return ls;
102720Sigor@sysoev.ru }
102820Sigor@sysoev.ru 
102920Sigor@sysoev.ru 
103020Sigor@sysoev.ru static nxt_int_t
103120Sigor@sysoev.ru nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt)
103220Sigor@sysoev.ru {
103320Sigor@sysoev.ru     size_t  length;
103420Sigor@sysoev.ru     char    hostname[NXT_MAXHOSTNAMELEN + 1];
103520Sigor@sysoev.ru 
103620Sigor@sysoev.ru     if (gethostname(hostname, NXT_MAXHOSTNAMELEN) != 0) {
1037564Svbart@nginx.com         nxt_alert(task, "gethostname() failed %E", nxt_errno);
103820Sigor@sysoev.ru         return NXT_ERROR;
103920Sigor@sysoev.ru     }
104020Sigor@sysoev.ru 
104120Sigor@sysoev.ru     /*
104220Sigor@sysoev.ru      * Linux gethostname(2):
104320Sigor@sysoev.ru      *
104420Sigor@sysoev.ru      *    If the null-terminated hostname is too large to fit,
104520Sigor@sysoev.ru      *    then the name is truncated, and no error is returned.
104620Sigor@sysoev.ru      *
104720Sigor@sysoev.ru      * For this reason an additional byte is reserved in the buffer.
104820Sigor@sysoev.ru      */
104920Sigor@sysoev.ru     hostname[NXT_MAXHOSTNAMELEN] = '\0';
105020Sigor@sysoev.ru 
105120Sigor@sysoev.ru     length = nxt_strlen(hostname);
105220Sigor@sysoev.ru     rt->hostname.length = length;
105320Sigor@sysoev.ru 
105465Sigor@sysoev.ru     rt->hostname.start = nxt_mp_nget(rt->mem_pool, length);
105520Sigor@sysoev.ru 
105620Sigor@sysoev.ru     if (rt->hostname.start != NULL) {
105720Sigor@sysoev.ru         nxt_memcpy_lowcase(rt->hostname.start, (u_char *) hostname, length);
105820Sigor@sysoev.ru         return NXT_OK;
105920Sigor@sysoev.ru     }
106020Sigor@sysoev.ru 
106120Sigor@sysoev.ru     return NXT_ERROR;
106220Sigor@sysoev.ru }
106320Sigor@sysoev.ru 
106420Sigor@sysoev.ru 
106520Sigor@sysoev.ru static nxt_int_t
106620Sigor@sysoev.ru nxt_runtime_log_files_init(nxt_runtime_t *rt)
106720Sigor@sysoev.ru {
106820Sigor@sysoev.ru     nxt_file_t  *file;
106920Sigor@sysoev.ru     nxt_list_t  *log_files;
107020Sigor@sysoev.ru 
107120Sigor@sysoev.ru     log_files = nxt_list_create(rt->mem_pool, 1, sizeof(nxt_file_t));
107220Sigor@sysoev.ru 
107320Sigor@sysoev.ru     if (nxt_fast_path(log_files != NULL)) {
107420Sigor@sysoev.ru         rt->log_files = log_files;
107520Sigor@sysoev.ru 
1076230Sigor@sysoev.ru         /* Preallocate the main log.  This allocation cannot fail. */
107720Sigor@sysoev.ru         file = nxt_list_zero_add(log_files);
107820Sigor@sysoev.ru 
107920Sigor@sysoev.ru         file->fd = NXT_FILE_INVALID;
1080564Svbart@nginx.com         file->log_level = NXT_LOG_ALERT;
108120Sigor@sysoev.ru 
108220Sigor@sysoev.ru         return NXT_OK;
108320Sigor@sysoev.ru     }
108420Sigor@sysoev.ru 
108520Sigor@sysoev.ru     return NXT_ERROR;
108620Sigor@sysoev.ru }
108720Sigor@sysoev.ru 
108820Sigor@sysoev.ru 
108920Sigor@sysoev.ru nxt_file_t *
109020Sigor@sysoev.ru nxt_runtime_log_file_add(nxt_runtime_t *rt, nxt_str_t *name)
109120Sigor@sysoev.ru {
109220Sigor@sysoev.ru     nxt_int_t            ret;
109320Sigor@sysoev.ru     nxt_file_t           *file;
109420Sigor@sysoev.ru     nxt_file_name_str_t  file_name;
109520Sigor@sysoev.ru 
1096230Sigor@sysoev.ru     ret = nxt_file_name_create(rt->mem_pool, &file_name, "V%Z", name);
109720Sigor@sysoev.ru 
109820Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
109920Sigor@sysoev.ru         return NULL;
110020Sigor@sysoev.ru     }
110120Sigor@sysoev.ru 
110220Sigor@sysoev.ru     nxt_list_each(file, rt->log_files) {
110320Sigor@sysoev.ru 
110420Sigor@sysoev.ru         /* STUB: hardecoded case sensitive/insensitive. */
110520Sigor@sysoev.ru 
110620Sigor@sysoev.ru         if (file->name != NULL
110720Sigor@sysoev.ru             && nxt_file_name_eq(file->name, file_name.start))
110820Sigor@sysoev.ru         {
110920Sigor@sysoev.ru             return file;
111020Sigor@sysoev.ru         }
111120Sigor@sysoev.ru 
111220Sigor@sysoev.ru     } nxt_list_loop;
111320Sigor@sysoev.ru 
111420Sigor@sysoev.ru     file = nxt_list_zero_add(rt->log_files);
111520Sigor@sysoev.ru 
111620Sigor@sysoev.ru     if (nxt_slow_path(file == NULL)) {
111720Sigor@sysoev.ru         return NULL;
111820Sigor@sysoev.ru     }
111920Sigor@sysoev.ru 
112020Sigor@sysoev.ru     file->fd = NXT_FILE_INVALID;
1121564Svbart@nginx.com     file->log_level = NXT_LOG_ALERT;
112220Sigor@sysoev.ru     file->name = file_name.start;
112320Sigor@sysoev.ru 
112420Sigor@sysoev.ru     return file;
112520Sigor@sysoev.ru }
112620Sigor@sysoev.ru 
112720Sigor@sysoev.ru 
112820Sigor@sysoev.ru static nxt_int_t
112920Sigor@sysoev.ru nxt_runtime_log_files_create(nxt_task_t *task, nxt_runtime_t *rt)
113020Sigor@sysoev.ru {
113120Sigor@sysoev.ru     nxt_int_t   ret;
113220Sigor@sysoev.ru     nxt_file_t  *file;
113320Sigor@sysoev.ru 
113420Sigor@sysoev.ru     nxt_list_each(file, rt->log_files) {
113520Sigor@sysoev.ru 
113620Sigor@sysoev.ru         ret = nxt_file_open(task, file, O_WRONLY | O_APPEND, O_CREAT,
113720Sigor@sysoev.ru                             NXT_FILE_OWNER_ACCESS);
113820Sigor@sysoev.ru 
113920Sigor@sysoev.ru         if (ret != NXT_OK) {
114020Sigor@sysoev.ru             return NXT_ERROR;
114120Sigor@sysoev.ru         }
114220Sigor@sysoev.ru 
114320Sigor@sysoev.ru     } nxt_list_loop;
114420Sigor@sysoev.ru 
114520Sigor@sysoev.ru     file = nxt_list_first(rt->log_files);
114620Sigor@sysoev.ru 
114720Sigor@sysoev.ru     return nxt_file_stderr(file);
114820Sigor@sysoev.ru }
114920Sigor@sysoev.ru 
115020Sigor@sysoev.ru 
115120Sigor@sysoev.ru nxt_int_t
115220Sigor@sysoev.ru nxt_runtime_listen_sockets_create(nxt_task_t *task, nxt_runtime_t *rt)
115320Sigor@sysoev.ru {
115420Sigor@sysoev.ru     nxt_int_t            ret;
115520Sigor@sysoev.ru     nxt_uint_t           c, p, ncurr, nprev;
115620Sigor@sysoev.ru     nxt_listen_socket_t  *curr, *prev;
115720Sigor@sysoev.ru 
115820Sigor@sysoev.ru     curr = rt->listen_sockets->elts;
115920Sigor@sysoev.ru     ncurr = rt->listen_sockets->nelts;
116020Sigor@sysoev.ru 
116120Sigor@sysoev.ru     if (rt->inherited_sockets != NULL) {
116220Sigor@sysoev.ru         prev = rt->inherited_sockets->elts;
116320Sigor@sysoev.ru         nprev = rt->inherited_sockets->nelts;
116420Sigor@sysoev.ru 
116520Sigor@sysoev.ru     } else {
116620Sigor@sysoev.ru         prev = NULL;
116720Sigor@sysoev.ru         nprev = 0;
116820Sigor@sysoev.ru     }
116920Sigor@sysoev.ru 
117020Sigor@sysoev.ru     for (c = 0; c < ncurr; c++) {
117120Sigor@sysoev.ru 
117220Sigor@sysoev.ru         for (p = 0; p < nprev; p++) {
117320Sigor@sysoev.ru 
117420Sigor@sysoev.ru             if (nxt_sockaddr_cmp(curr[c].sockaddr, prev[p].sockaddr)) {
117520Sigor@sysoev.ru 
117620Sigor@sysoev.ru                 ret = nxt_listen_socket_update(task, &curr[c], &prev[p]);
117720Sigor@sysoev.ru                 if (ret != NXT_OK) {
117820Sigor@sysoev.ru                     return NXT_ERROR;
117920Sigor@sysoev.ru                 }
118020Sigor@sysoev.ru 
118120Sigor@sysoev.ru                 goto next;
118220Sigor@sysoev.ru             }
118320Sigor@sysoev.ru         }
118420Sigor@sysoev.ru 
118520Sigor@sysoev.ru         if (nxt_listen_socket_create(task, &curr[c], 0) != NXT_OK) {
118620Sigor@sysoev.ru             return NXT_ERROR;
118720Sigor@sysoev.ru         }
118820Sigor@sysoev.ru 
118920Sigor@sysoev.ru     next:
119020Sigor@sysoev.ru 
119120Sigor@sysoev.ru         continue;
119220Sigor@sysoev.ru     }
119320Sigor@sysoev.ru 
119420Sigor@sysoev.ru     return NXT_OK;
119520Sigor@sysoev.ru }
119620Sigor@sysoev.ru 
119720Sigor@sysoev.ru 
119820Sigor@sysoev.ru nxt_int_t
119920Sigor@sysoev.ru nxt_runtime_listen_sockets_enable(nxt_task_t *task, nxt_runtime_t *rt)
120020Sigor@sysoev.ru {
120120Sigor@sysoev.ru     nxt_uint_t           i, n;
120220Sigor@sysoev.ru     nxt_listen_socket_t  *ls;
120320Sigor@sysoev.ru 
120420Sigor@sysoev.ru     ls = rt->listen_sockets->elts;
120520Sigor@sysoev.ru     n = rt->listen_sockets->nelts;
120620Sigor@sysoev.ru 
120720Sigor@sysoev.ru     for (i = 0; i < n; i++) {
120820Sigor@sysoev.ru         if (ls[i].flags == NXT_NONBLOCK) {
120954Sigor@sysoev.ru             if (nxt_listen_event(task, &ls[i]) == NULL) {
121020Sigor@sysoev.ru                 return NXT_ERROR;
121120Sigor@sysoev.ru             }
121220Sigor@sysoev.ru         }
121320Sigor@sysoev.ru     }
121420Sigor@sysoev.ru 
121520Sigor@sysoev.ru     return NXT_OK;
121620Sigor@sysoev.ru }
121720Sigor@sysoev.ru 
121820Sigor@sysoev.ru 
121920Sigor@sysoev.ru nxt_str_t *
122065Sigor@sysoev.ru nxt_current_directory(nxt_mp_t *mp)
122120Sigor@sysoev.ru {
122220Sigor@sysoev.ru     size_t     length;
122320Sigor@sysoev.ru     u_char     *p;
122420Sigor@sysoev.ru     nxt_str_t  *name;
122520Sigor@sysoev.ru     char       buf[NXT_MAX_PATH_LEN];
122620Sigor@sysoev.ru 
122720Sigor@sysoev.ru     length = nxt_dir_current(buf, NXT_MAX_PATH_LEN);
122820Sigor@sysoev.ru 
122920Sigor@sysoev.ru     if (nxt_fast_path(length != 0)) {
123020Sigor@sysoev.ru         name = nxt_str_alloc(mp, length + 1);
123120Sigor@sysoev.ru 
123220Sigor@sysoev.ru         if (nxt_fast_path(name != NULL)) {
123320Sigor@sysoev.ru             p = nxt_cpymem(name->start, buf, length);
123420Sigor@sysoev.ru             *p = '/';
123520Sigor@sysoev.ru 
123620Sigor@sysoev.ru             return name;
123720Sigor@sysoev.ru         }
123820Sigor@sysoev.ru     }
123920Sigor@sysoev.ru 
124020Sigor@sysoev.ru     return NULL;
124120Sigor@sysoev.ru }
124220Sigor@sysoev.ru 
124320Sigor@sysoev.ru 
124420Sigor@sysoev.ru static nxt_int_t
124520Sigor@sysoev.ru nxt_runtime_pid_file_create(nxt_task_t *task, nxt_file_name_t *pid_file)
124620Sigor@sysoev.ru {
124720Sigor@sysoev.ru     ssize_t     length;
124820Sigor@sysoev.ru     nxt_int_t   n;
124920Sigor@sysoev.ru     nxt_file_t  file;
1250704Sigor@sysoev.ru     u_char      pid[NXT_INT64_T_LEN + nxt_length("\n")];
125120Sigor@sysoev.ru 
125220Sigor@sysoev.ru     nxt_memzero(&file, sizeof(nxt_file_t));
125320Sigor@sysoev.ru 
125420Sigor@sysoev.ru     file.name = pid_file;
125520Sigor@sysoev.ru 
125620Sigor@sysoev.ru     n = nxt_file_open(task, &file, O_WRONLY, O_CREAT | O_TRUNC,
125720Sigor@sysoev.ru                       NXT_FILE_DEFAULT_ACCESS);
125820Sigor@sysoev.ru 
125920Sigor@sysoev.ru     if (n != NXT_OK) {
126020Sigor@sysoev.ru         return NXT_ERROR;
126120Sigor@sysoev.ru     }
126220Sigor@sysoev.ru 
126320Sigor@sysoev.ru     length = nxt_sprintf(pid, pid + sizeof(pid), "%PI%n", nxt_pid) - pid;
126420Sigor@sysoev.ru 
126520Sigor@sysoev.ru     if (nxt_file_write(&file, pid, length, 0) != length) {
126620Sigor@sysoev.ru         return NXT_ERROR;
126720Sigor@sysoev.ru     }
126820Sigor@sysoev.ru 
126920Sigor@sysoev.ru     nxt_file_close(task, &file);
127020Sigor@sysoev.ru 
127120Sigor@sysoev.ru     return NXT_OK;
127220Sigor@sysoev.ru }
127320Sigor@sysoev.ru 
127420Sigor@sysoev.ru 
127520Sigor@sysoev.ru nxt_process_t *
127642Smax.romanov@nginx.com nxt_runtime_process_new(nxt_runtime_t *rt)
127720Sigor@sysoev.ru {
127820Sigor@sysoev.ru     nxt_process_t  *process;
127920Sigor@sysoev.ru 
128020Sigor@sysoev.ru     /* TODO: memory failures. */
128120Sigor@sysoev.ru 
128265Sigor@sysoev.ru     process = nxt_mp_zalloc(rt->mem_pool, sizeof(nxt_process_t));
128342Smax.romanov@nginx.com     if (nxt_slow_path(process == NULL)) {
128442Smax.romanov@nginx.com         return NULL;
128542Smax.romanov@nginx.com     }
128642Smax.romanov@nginx.com 
128742Smax.romanov@nginx.com     nxt_queue_init(&process->ports);
128842Smax.romanov@nginx.com 
1289364Smax.romanov@nginx.com     nxt_thread_mutex_create(&process->incoming.mutex);
1290364Smax.romanov@nginx.com     nxt_thread_mutex_create(&process->outgoing.mutex);
1291141Smax.romanov@nginx.com     nxt_thread_mutex_create(&process->cp_mutex);
129290Smax.romanov@nginx.com 
1293349Smax.romanov@nginx.com     process->use_count = 1;
1294349Smax.romanov@nginx.com 
129542Smax.romanov@nginx.com     return process;
129642Smax.romanov@nginx.com }
129742Smax.romanov@nginx.com 
129842Smax.romanov@nginx.com 
1299196Smax.romanov@nginx.com static void
1300141Smax.romanov@nginx.com nxt_runtime_process_destroy(nxt_runtime_t *rt, nxt_process_t *process)
1301141Smax.romanov@nginx.com {
1302597Sigor@sysoev.ru     nxt_port_t  *port;
1303341Smax.romanov@nginx.com 
1304349Smax.romanov@nginx.com     nxt_assert(process->use_count == 0);
1305196Smax.romanov@nginx.com     nxt_assert(process->registered == 0);
1306164Smax.romanov@nginx.com 
1307364Smax.romanov@nginx.com     nxt_port_mmaps_destroy(&process->incoming, 1);
1308364Smax.romanov@nginx.com     nxt_port_mmaps_destroy(&process->outgoing, 1);
1309141Smax.romanov@nginx.com 
1310597Sigor@sysoev.ru     do {
1311597Sigor@sysoev.ru         port = nxt_port_hash_retrieve(&process->connected_ports);
1312597Sigor@sysoev.ru 
1313597Sigor@sysoev.ru     } while (port != NULL);
1314141Smax.romanov@nginx.com 
1315364Smax.romanov@nginx.com     nxt_thread_mutex_destroy(&process->incoming.mutex);
1316364Smax.romanov@nginx.com     nxt_thread_mutex_destroy(&process->outgoing.mutex);
1317141Smax.romanov@nginx.com     nxt_thread_mutex_destroy(&process->cp_mutex);
1318141Smax.romanov@nginx.com 
1319141Smax.romanov@nginx.com     nxt_mp_free(rt->mem_pool, process);
1320141Smax.romanov@nginx.com }
1321141Smax.romanov@nginx.com 
1322141Smax.romanov@nginx.com 
132342Smax.romanov@nginx.com static nxt_int_t
132442Smax.romanov@nginx.com nxt_runtime_lvlhsh_pid_test(nxt_lvlhsh_query_t *lhq, void *data)
132542Smax.romanov@nginx.com {
132642Smax.romanov@nginx.com     nxt_process_t  *process;
132742Smax.romanov@nginx.com 
132842Smax.romanov@nginx.com     process = data;
132942Smax.romanov@nginx.com 
1330277Sigor@sysoev.ru     if (lhq->key.length == sizeof(nxt_pid_t)
1331277Sigor@sysoev.ru         && *(nxt_pid_t *) lhq->key.start == process->pid)
1332277Sigor@sysoev.ru     {
133342Smax.romanov@nginx.com         return NXT_OK;
133442Smax.romanov@nginx.com     }
133542Smax.romanov@nginx.com 
133642Smax.romanov@nginx.com     return NXT_DECLINED;
133742Smax.romanov@nginx.com }
133842Smax.romanov@nginx.com 
133942Smax.romanov@nginx.com static const nxt_lvlhsh_proto_t  lvlhsh_processes_proto  nxt_aligned(64) = {
134042Smax.romanov@nginx.com     NXT_LVLHSH_DEFAULT,
134142Smax.romanov@nginx.com     nxt_runtime_lvlhsh_pid_test,
134242Smax.romanov@nginx.com     nxt_lvlhsh_alloc,
134342Smax.romanov@nginx.com     nxt_lvlhsh_free,
134442Smax.romanov@nginx.com };
134542Smax.romanov@nginx.com 
134642Smax.romanov@nginx.com 
1347196Smax.romanov@nginx.com nxt_inline void
1348196Smax.romanov@nginx.com nxt_runtime_process_lhq_pid(nxt_lvlhsh_query_t *lhq, nxt_pid_t *pid)
1349196Smax.romanov@nginx.com {
1350196Smax.romanov@nginx.com     lhq->key_hash = nxt_murmur_hash2(pid, sizeof(*pid));
1351196Smax.romanov@nginx.com     lhq->key.length = sizeof(*pid);
1352196Smax.romanov@nginx.com     lhq->key.start = (u_char *) pid;
1353196Smax.romanov@nginx.com     lhq->proto = &lvlhsh_processes_proto;
1354196Smax.romanov@nginx.com }
1355196Smax.romanov@nginx.com 
1356196Smax.romanov@nginx.com 
135742Smax.romanov@nginx.com nxt_process_t *
135842Smax.romanov@nginx.com nxt_runtime_process_find(nxt_runtime_t *rt, nxt_pid_t pid)
135942Smax.romanov@nginx.com {
1360196Smax.romanov@nginx.com     nxt_process_t       *process;
136142Smax.romanov@nginx.com     nxt_lvlhsh_query_t  lhq;
136242Smax.romanov@nginx.com 
1363196Smax.romanov@nginx.com     process = NULL;
1364196Smax.romanov@nginx.com 
1365196Smax.romanov@nginx.com     nxt_runtime_process_lhq_pid(&lhq, &pid);
1366196Smax.romanov@nginx.com 
1367196Smax.romanov@nginx.com     nxt_thread_mutex_lock(&rt->processes_mutex);
136842Smax.romanov@nginx.com 
136942Smax.romanov@nginx.com     if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) {
1370196Smax.romanov@nginx.com         process = lhq.value;
1371196Smax.romanov@nginx.com 
1372196Smax.romanov@nginx.com     } else {
1373196Smax.romanov@nginx.com         nxt_thread_log_debug("process %PI not found", pid);
137442Smax.romanov@nginx.com     }
137542Smax.romanov@nginx.com 
1376196Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&rt->processes_mutex);
137742Smax.romanov@nginx.com 
1378196Smax.romanov@nginx.com     return process;
137942Smax.romanov@nginx.com }
138042Smax.romanov@nginx.com 
138142Smax.romanov@nginx.com 
138242Smax.romanov@nginx.com nxt_process_t *
138342Smax.romanov@nginx.com nxt_runtime_process_get(nxt_runtime_t *rt, nxt_pid_t pid)
138442Smax.romanov@nginx.com {
138542Smax.romanov@nginx.com     nxt_process_t       *process;
138642Smax.romanov@nginx.com     nxt_lvlhsh_query_t  lhq;
138742Smax.romanov@nginx.com 
1388196Smax.romanov@nginx.com     nxt_runtime_process_lhq_pid(&lhq, &pid);
1389196Smax.romanov@nginx.com 
1390196Smax.romanov@nginx.com     nxt_thread_mutex_lock(&rt->processes_mutex);
139142Smax.romanov@nginx.com 
139242Smax.romanov@nginx.com     if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) {
139342Smax.romanov@nginx.com         nxt_thread_log_debug("process %PI found", pid);
1394196Smax.romanov@nginx.com 
1395196Smax.romanov@nginx.com         nxt_thread_mutex_unlock(&rt->processes_mutex);
1396349Smax.romanov@nginx.com 
1397349Smax.romanov@nginx.com         process = lhq.value;
1398349Smax.romanov@nginx.com         process->use_count++;
1399349Smax.romanov@nginx.com 
1400349Smax.romanov@nginx.com         return process;
140142Smax.romanov@nginx.com     }
140242Smax.romanov@nginx.com 
140342Smax.romanov@nginx.com     process = nxt_runtime_process_new(rt);
140420Sigor@sysoev.ru     if (nxt_slow_path(process == NULL)) {
1405382Smax.romanov@nginx.com 
1406382Smax.romanov@nginx.com         nxt_thread_mutex_unlock(&rt->processes_mutex);
1407382Smax.romanov@nginx.com 
140820Sigor@sysoev.ru         return NULL;
140920Sigor@sysoev.ru     }
141020Sigor@sysoev.ru 
141142Smax.romanov@nginx.com     process->pid = pid;
141242Smax.romanov@nginx.com 
141342Smax.romanov@nginx.com     lhq.replace = 0;
141442Smax.romanov@nginx.com     lhq.value = process;
141542Smax.romanov@nginx.com     lhq.pool = rt->mem_pool;
141642Smax.romanov@nginx.com 
141742Smax.romanov@nginx.com     switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) {
141842Smax.romanov@nginx.com 
141942Smax.romanov@nginx.com     case NXT_OK:
142042Smax.romanov@nginx.com         if (rt->nprocesses == 0) {
142142Smax.romanov@nginx.com             rt->mprocess = process;
142242Smax.romanov@nginx.com         }
142342Smax.romanov@nginx.com 
142442Smax.romanov@nginx.com         rt->nprocesses++;
142542Smax.romanov@nginx.com 
1426196Smax.romanov@nginx.com         process->registered = 1;
1427196Smax.romanov@nginx.com 
142842Smax.romanov@nginx.com         nxt_thread_log_debug("process %PI insert", pid);
142942Smax.romanov@nginx.com         break;
143042Smax.romanov@nginx.com 
143142Smax.romanov@nginx.com     default:
143242Smax.romanov@nginx.com         nxt_thread_log_debug("process %PI insert failed", pid);
143342Smax.romanov@nginx.com         break;
143420Sigor@sysoev.ru     }
143520Sigor@sysoev.ru 
1436196Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&rt->processes_mutex);
1437196Smax.romanov@nginx.com 
143820Sigor@sysoev.ru     return process;
143920Sigor@sysoev.ru }
144042Smax.romanov@nginx.com 
144142Smax.romanov@nginx.com 
144242Smax.romanov@nginx.com void
1443343Smax.romanov@nginx.com nxt_runtime_process_add(nxt_task_t *task, nxt_process_t *process)
144442Smax.romanov@nginx.com {
144542Smax.romanov@nginx.com     nxt_port_t          *port;
1446343Smax.romanov@nginx.com     nxt_runtime_t       *rt;
144742Smax.romanov@nginx.com     nxt_lvlhsh_query_t  lhq;
144842Smax.romanov@nginx.com 
1449196Smax.romanov@nginx.com     nxt_assert(process->registered == 0);
1450196Smax.romanov@nginx.com 
1451343Smax.romanov@nginx.com     rt = task->thread->runtime;
1452343Smax.romanov@nginx.com 
1453196Smax.romanov@nginx.com     nxt_runtime_process_lhq_pid(&lhq, &process->pid);
1454196Smax.romanov@nginx.com 
145542Smax.romanov@nginx.com     lhq.replace = 0;
145642Smax.romanov@nginx.com     lhq.value = process;
145742Smax.romanov@nginx.com     lhq.pool = rt->mem_pool;
145842Smax.romanov@nginx.com 
1459196Smax.romanov@nginx.com     nxt_thread_mutex_lock(&rt->processes_mutex);
1460196Smax.romanov@nginx.com 
146142Smax.romanov@nginx.com     switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) {
146242Smax.romanov@nginx.com 
146342Smax.romanov@nginx.com     case NXT_OK:
146442Smax.romanov@nginx.com         if (rt->nprocesses == 0) {
146542Smax.romanov@nginx.com             rt->mprocess = process;
146642Smax.romanov@nginx.com         }
146742Smax.romanov@nginx.com 
146842Smax.romanov@nginx.com         rt->nprocesses++;
146942Smax.romanov@nginx.com 
147042Smax.romanov@nginx.com         nxt_process_port_each(process, port) {
147142Smax.romanov@nginx.com 
1472141Smax.romanov@nginx.com             port->pid = process->pid;
1473141Smax.romanov@nginx.com 
1474343Smax.romanov@nginx.com             nxt_runtime_port_add(task, port);
147542Smax.romanov@nginx.com 
147642Smax.romanov@nginx.com         } nxt_process_port_loop;
147742Smax.romanov@nginx.com 
1478196Smax.romanov@nginx.com         process->registered = 1;
1479196Smax.romanov@nginx.com 
1480196Smax.romanov@nginx.com         nxt_thread_log_debug("process %PI added", process->pid);
148142Smax.romanov@nginx.com         break;
148242Smax.romanov@nginx.com 
148342Smax.romanov@nginx.com     default:
1484196Smax.romanov@nginx.com         nxt_thread_log_debug("process %PI failed to add", process->pid);
148542Smax.romanov@nginx.com         break;
148642Smax.romanov@nginx.com     }
1487196Smax.romanov@nginx.com 
1488196Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&rt->processes_mutex);
1489196Smax.romanov@nginx.com }
1490196Smax.romanov@nginx.com 
1491196Smax.romanov@nginx.com 
1492196Smax.romanov@nginx.com static nxt_process_t *
1493196Smax.romanov@nginx.com nxt_runtime_process_remove_pid(nxt_runtime_t *rt, nxt_pid_t pid)
1494196Smax.romanov@nginx.com {
1495196Smax.romanov@nginx.com     nxt_process_t       *process;
1496196Smax.romanov@nginx.com     nxt_lvlhsh_query_t  lhq;
1497196Smax.romanov@nginx.com 
1498196Smax.romanov@nginx.com     process = NULL;
1499196Smax.romanov@nginx.com 
1500196Smax.romanov@nginx.com     nxt_runtime_process_lhq_pid(&lhq, &pid);
1501196Smax.romanov@nginx.com 
1502196Smax.romanov@nginx.com     lhq.pool = rt->mem_pool;
1503196Smax.romanov@nginx.com 
1504196Smax.romanov@nginx.com     nxt_thread_mutex_lock(&rt->processes_mutex);
1505196Smax.romanov@nginx.com 
1506196Smax.romanov@nginx.com     switch (nxt_lvlhsh_delete(&rt->processes, &lhq)) {
1507196Smax.romanov@nginx.com 
1508196Smax.romanov@nginx.com     case NXT_OK:
1509196Smax.romanov@nginx.com         rt->nprocesses--;
1510196Smax.romanov@nginx.com 
1511196Smax.romanov@nginx.com         process = lhq.value;
1512196Smax.romanov@nginx.com 
1513196Smax.romanov@nginx.com         process->registered = 0;
1514196Smax.romanov@nginx.com 
1515196Smax.romanov@nginx.com         nxt_thread_log_debug("process %PI removed", pid);
1516196Smax.romanov@nginx.com         break;
1517196Smax.romanov@nginx.com 
1518196Smax.romanov@nginx.com     default:
1519196Smax.romanov@nginx.com         nxt_thread_log_debug("process %PI remove failed", pid);
1520196Smax.romanov@nginx.com         break;
1521196Smax.romanov@nginx.com     }
1522196Smax.romanov@nginx.com 
1523196Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&rt->processes_mutex);
1524196Smax.romanov@nginx.com 
1525196Smax.romanov@nginx.com     return process;
152642Smax.romanov@nginx.com }
152742Smax.romanov@nginx.com 
152842Smax.romanov@nginx.com 
152942Smax.romanov@nginx.com void
1530349Smax.romanov@nginx.com nxt_process_use(nxt_task_t *task, nxt_process_t *process, int i)
153142Smax.romanov@nginx.com {
1532343Smax.romanov@nginx.com     nxt_runtime_t  *rt;
1533343Smax.romanov@nginx.com 
1534349Smax.romanov@nginx.com     process->use_count += i;
1535349Smax.romanov@nginx.com 
1536349Smax.romanov@nginx.com     if (process->use_count == 0) {
1537349Smax.romanov@nginx.com         rt = task->thread->runtime;
1538349Smax.romanov@nginx.com 
1539196Smax.romanov@nginx.com         if (process->registered == 1) {
1540196Smax.romanov@nginx.com             nxt_runtime_process_remove_pid(rt, process->pid);
1541164Smax.romanov@nginx.com         }
1542164Smax.romanov@nginx.com 
1543196Smax.romanov@nginx.com         nxt_runtime_process_destroy(rt, process);
154442Smax.romanov@nginx.com     }
154542Smax.romanov@nginx.com }
154642Smax.romanov@nginx.com 
154742Smax.romanov@nginx.com 
154842Smax.romanov@nginx.com nxt_process_t *
154942Smax.romanov@nginx.com nxt_runtime_process_first(nxt_runtime_t *rt, nxt_lvlhsh_each_t *lhe)
155042Smax.romanov@nginx.com {
1551598Sigor@sysoev.ru     nxt_lvlhsh_each_init(lhe, &lvlhsh_processes_proto);
155242Smax.romanov@nginx.com 
155342Smax.romanov@nginx.com     return nxt_runtime_process_next(rt, lhe);
155442Smax.romanov@nginx.com }
155542Smax.romanov@nginx.com 
155642Smax.romanov@nginx.com 
155742Smax.romanov@nginx.com void
1558343Smax.romanov@nginx.com nxt_runtime_port_add(nxt_task_t *task, nxt_port_t *port)
155942Smax.romanov@nginx.com {
1560348Smax.romanov@nginx.com     nxt_int_t      res;
1561343Smax.romanov@nginx.com     nxt_runtime_t  *rt;
1562343Smax.romanov@nginx.com 
1563343Smax.romanov@nginx.com     rt = task->thread->runtime;
1564343Smax.romanov@nginx.com 
1565348Smax.romanov@nginx.com     res = nxt_port_hash_add(&rt->ports, port);
1566348Smax.romanov@nginx.com 
1567348Smax.romanov@nginx.com     if (res != NXT_OK) {
1568348Smax.romanov@nginx.com         return;
1569348Smax.romanov@nginx.com     }
1570141Smax.romanov@nginx.com 
1571141Smax.romanov@nginx.com     rt->port_by_type[port->type] = port;
1572343Smax.romanov@nginx.com 
1573343Smax.romanov@nginx.com     nxt_port_use(task, port, 1);
157442Smax.romanov@nginx.com }
157542Smax.romanov@nginx.com 
157642Smax.romanov@nginx.com 
157742Smax.romanov@nginx.com void
1578343Smax.romanov@nginx.com nxt_runtime_port_remove(nxt_task_t *task, nxt_port_t *port)
157942Smax.romanov@nginx.com {
1580348Smax.romanov@nginx.com     nxt_int_t      res;
1581343Smax.romanov@nginx.com     nxt_runtime_t  *rt;
1582343Smax.romanov@nginx.com 
1583343Smax.romanov@nginx.com     rt = task->thread->runtime;
1584343Smax.romanov@nginx.com 
1585348Smax.romanov@nginx.com     res = nxt_port_hash_remove(&rt->ports, port);
1586348Smax.romanov@nginx.com 
1587348Smax.romanov@nginx.com     if (res != NXT_OK) {
1588348Smax.romanov@nginx.com         return;
1589348Smax.romanov@nginx.com     }
1590125Smax.romanov@nginx.com 
1591141Smax.romanov@nginx.com     if (rt->port_by_type[port->type] == port) {
1592141Smax.romanov@nginx.com         rt->port_by_type[port->type] = NULL;
1593141Smax.romanov@nginx.com     }
1594343Smax.romanov@nginx.com 
1595343Smax.romanov@nginx.com     nxt_port_use(task, port, -1);
159642Smax.romanov@nginx.com }
159742Smax.romanov@nginx.com 
159842Smax.romanov@nginx.com 
159942Smax.romanov@nginx.com nxt_port_t *
160042Smax.romanov@nginx.com nxt_runtime_port_find(nxt_runtime_t *rt, nxt_pid_t pid,
160142Smax.romanov@nginx.com     nxt_port_id_t port_id)
160242Smax.romanov@nginx.com {
160375Smax.romanov@nginx.com     return nxt_port_hash_find(&rt->ports, pid, port_id);
160442Smax.romanov@nginx.com }
1605