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); 2220Sigor@sysoev.ru static void nxt_runtime_initial_start(nxt_task_t *task); 2320Sigor@sysoev.ru static void nxt_single_process_start(nxt_thread_t *thr, nxt_task_t *task, 2420Sigor@sysoev.ru nxt_runtime_t *rt); 2520Sigor@sysoev.ru static void nxt_runtime_close_idle_connections(nxt_event_engine_t *engine); 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_sockaddr_t *nxt_runtime_sockaddr_parse(nxt_task_t *task, 3265Sigor@sysoev.ru nxt_mp_t *mp, nxt_str_t *addr); 3320Sigor@sysoev.ru static nxt_sockaddr_t *nxt_runtime_sockaddr_unix_parse(nxt_task_t *task, 3465Sigor@sysoev.ru nxt_mp_t *mp, nxt_str_t *addr); 3520Sigor@sysoev.ru static nxt_sockaddr_t *nxt_runtime_sockaddr_inet6_parse(nxt_task_t *task, 3665Sigor@sysoev.ru nxt_mp_t *mp, nxt_str_t *addr); 3720Sigor@sysoev.ru static nxt_sockaddr_t *nxt_runtime_sockaddr_inet_parse(nxt_task_t *task, 3865Sigor@sysoev.ru nxt_mp_t *mp, nxt_str_t *addr); 3920Sigor@sysoev.ru static nxt_int_t nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt); 4020Sigor@sysoev.ru static nxt_int_t nxt_runtime_log_files_init(nxt_runtime_t *rt); 4120Sigor@sysoev.ru static nxt_int_t nxt_runtime_log_files_create(nxt_task_t *task, 4220Sigor@sysoev.ru nxt_runtime_t *rt); 4320Sigor@sysoev.ru static nxt_int_t nxt_runtime_pid_file_create(nxt_task_t *task, 4420Sigor@sysoev.ru nxt_file_name_t *pid_file); 4520Sigor@sysoev.ru static void nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt, 4620Sigor@sysoev.ru nxt_runtime_cont_t cont); 47223Sigor@sysoev.ru static void nxt_runtime_thread_pool_init(void); 48223Sigor@sysoev.ru static void nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj, 49223Sigor@sysoev.ru void *data); 50196Smax.romanov@nginx.com static void nxt_runtime_process_destroy(nxt_runtime_t *rt, 51196Smax.romanov@nginx.com nxt_process_t *process); 52196Smax.romanov@nginx.com static nxt_process_t *nxt_runtime_process_remove_pid(nxt_runtime_t *rt, 53196Smax.romanov@nginx.com nxt_pid_t pid); 54196Smax.romanov@nginx.com 5520Sigor@sysoev.ru 5620Sigor@sysoev.ru nxt_int_t 5720Sigor@sysoev.ru nxt_runtime_create(nxt_task_t *task) 5820Sigor@sysoev.ru { 59216Sigor@sysoev.ru nxt_mp_t *mp; 60216Sigor@sysoev.ru nxt_int_t ret; 61216Sigor@sysoev.ru nxt_array_t *listen_sockets; 62216Sigor@sysoev.ru nxt_runtime_t *rt; 63216Sigor@sysoev.ru nxt_app_lang_module_t *lang; 6420Sigor@sysoev.ru 6565Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 6620Sigor@sysoev.ru 6720Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 6820Sigor@sysoev.ru return NXT_ERROR; 6920Sigor@sysoev.ru } 7020Sigor@sysoev.ru 7165Sigor@sysoev.ru rt = nxt_mp_zget(mp, sizeof(nxt_runtime_t)); 7265Sigor@sysoev.ru if (nxt_slow_path(rt == NULL)) { 7365Sigor@sysoev.ru return NXT_ERROR; 7465Sigor@sysoev.ru } 7520Sigor@sysoev.ru 7620Sigor@sysoev.ru task->thread->runtime = rt; 7720Sigor@sysoev.ru rt->mem_pool = mp; 7820Sigor@sysoev.ru 79196Smax.romanov@nginx.com nxt_thread_mutex_create(&rt->processes_mutex); 80196Smax.romanov@nginx.com 8120Sigor@sysoev.ru rt->services = nxt_services_init(mp); 8220Sigor@sysoev.ru if (nxt_slow_path(rt->services == NULL)) { 8320Sigor@sysoev.ru goto fail; 8420Sigor@sysoev.ru } 8520Sigor@sysoev.ru 86216Sigor@sysoev.ru rt->languages = nxt_array_create(mp, 1, sizeof(nxt_app_lang_module_t)); 87216Sigor@sysoev.ru if (nxt_slow_path(rt->languages == NULL)) { 88216Sigor@sysoev.ru goto fail; 89216Sigor@sysoev.ru } 90216Sigor@sysoev.ru 91216Sigor@sysoev.ru /* Should not fail. */ 92216Sigor@sysoev.ru lang = nxt_array_add(rt->languages); 93216Sigor@sysoev.ru lang->type = (nxt_str_t) nxt_string("go"); 94*354Svbart@nginx.com lang->version = (u_char *) ""; 95216Sigor@sysoev.ru lang->file = NULL; 96216Sigor@sysoev.ru lang->module = &nxt_go_module; 97216Sigor@sysoev.ru 9820Sigor@sysoev.ru listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t)); 9920Sigor@sysoev.ru if (nxt_slow_path(listen_sockets == NULL)) { 10020Sigor@sysoev.ru goto fail; 10120Sigor@sysoev.ru } 10220Sigor@sysoev.ru 10320Sigor@sysoev.ru rt->listen_sockets = listen_sockets; 10420Sigor@sysoev.ru 10520Sigor@sysoev.ru ret = nxt_runtime_inherited_listen_sockets(task, rt); 10620Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 10720Sigor@sysoev.ru goto fail; 10820Sigor@sysoev.ru } 10920Sigor@sysoev.ru 11020Sigor@sysoev.ru if (nxt_runtime_hostname(task, rt) != NXT_OK) { 11120Sigor@sysoev.ru goto fail; 11220Sigor@sysoev.ru } 11320Sigor@sysoev.ru 11420Sigor@sysoev.ru if (nxt_slow_path(nxt_runtime_log_files_init(rt) != NXT_OK)) { 11520Sigor@sysoev.ru goto fail; 11620Sigor@sysoev.ru } 11720Sigor@sysoev.ru 11820Sigor@sysoev.ru if (nxt_runtime_event_engines(task, rt) != NXT_OK) { 11920Sigor@sysoev.ru goto fail; 12020Sigor@sysoev.ru } 12120Sigor@sysoev.ru 12220Sigor@sysoev.ru if (nxt_slow_path(nxt_runtime_thread_pools(task->thread, rt) != NXT_OK)) { 12320Sigor@sysoev.ru goto fail; 12420Sigor@sysoev.ru } 12520Sigor@sysoev.ru 12620Sigor@sysoev.ru rt->start = nxt_runtime_initial_start; 12720Sigor@sysoev.ru 128221Sigor@sysoev.ru if (nxt_runtime_conf_init(task, rt) != NXT_OK) { 129221Sigor@sysoev.ru goto fail; 130221Sigor@sysoev.ru } 131221Sigor@sysoev.ru 13220Sigor@sysoev.ru nxt_work_queue_add(&task->thread->engine->fast_work_queue, 13320Sigor@sysoev.ru nxt_runtime_start, task, rt, NULL); 13420Sigor@sysoev.ru 13520Sigor@sysoev.ru return NXT_OK; 13620Sigor@sysoev.ru 13720Sigor@sysoev.ru fail: 13820Sigor@sysoev.ru 13965Sigor@sysoev.ru nxt_mp_destroy(mp); 14020Sigor@sysoev.ru 14120Sigor@sysoev.ru return NXT_ERROR; 14220Sigor@sysoev.ru } 14320Sigor@sysoev.ru 14420Sigor@sysoev.ru 14520Sigor@sysoev.ru static nxt_int_t 14620Sigor@sysoev.ru nxt_runtime_inherited_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt) 14720Sigor@sysoev.ru { 14820Sigor@sysoev.ru u_char *v, *p; 14920Sigor@sysoev.ru nxt_int_t type; 15020Sigor@sysoev.ru nxt_array_t *inherited_sockets; 15120Sigor@sysoev.ru nxt_socket_t s; 15220Sigor@sysoev.ru nxt_listen_socket_t *ls; 15320Sigor@sysoev.ru 15420Sigor@sysoev.ru v = (u_char *) getenv("NGINX"); 15520Sigor@sysoev.ru 15620Sigor@sysoev.ru if (v == NULL) { 15720Sigor@sysoev.ru return nxt_runtime_systemd_listen_sockets(task, rt); 15820Sigor@sysoev.ru } 15920Sigor@sysoev.ru 16020Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "using inherited listen sockets: %s", v); 16120Sigor@sysoev.ru 16220Sigor@sysoev.ru inherited_sockets = nxt_array_create(rt->mem_pool, 16320Sigor@sysoev.ru 1, sizeof(nxt_listen_socket_t)); 16420Sigor@sysoev.ru if (inherited_sockets == NULL) { 16520Sigor@sysoev.ru return NXT_ERROR; 16620Sigor@sysoev.ru } 16720Sigor@sysoev.ru 16820Sigor@sysoev.ru rt->inherited_sockets = inherited_sockets; 16920Sigor@sysoev.ru 17020Sigor@sysoev.ru for (p = v; *p != '\0'; p++) { 17120Sigor@sysoev.ru 17220Sigor@sysoev.ru if (*p == ';') { 17320Sigor@sysoev.ru s = nxt_int_parse(v, p - v); 17420Sigor@sysoev.ru 17520Sigor@sysoev.ru if (nxt_slow_path(s < 0)) { 17620Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid socket number " 17720Sigor@sysoev.ru "\"%s\" in NGINX environment variable, " 17820Sigor@sysoev.ru "ignoring the rest of the variable", v); 17920Sigor@sysoev.ru return NXT_ERROR; 18020Sigor@sysoev.ru } 18120Sigor@sysoev.ru 18220Sigor@sysoev.ru v = p + 1; 18320Sigor@sysoev.ru 18420Sigor@sysoev.ru ls = nxt_array_zero_add(inherited_sockets); 18520Sigor@sysoev.ru if (nxt_slow_path(ls == NULL)) { 18620Sigor@sysoev.ru return NXT_ERROR; 18720Sigor@sysoev.ru } 18820Sigor@sysoev.ru 18920Sigor@sysoev.ru ls->socket = s; 19020Sigor@sysoev.ru 19120Sigor@sysoev.ru ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s); 19220Sigor@sysoev.ru if (nxt_slow_path(ls->sockaddr == NULL)) { 19320Sigor@sysoev.ru return NXT_ERROR; 19420Sigor@sysoev.ru } 19520Sigor@sysoev.ru 19620Sigor@sysoev.ru type = nxt_socket_getsockopt(task, s, SOL_SOCKET, SO_TYPE); 19720Sigor@sysoev.ru if (nxt_slow_path(type == -1)) { 19820Sigor@sysoev.ru return NXT_ERROR; 19920Sigor@sysoev.ru } 20020Sigor@sysoev.ru 20120Sigor@sysoev.ru ls->sockaddr->type = (uint16_t) type; 20220Sigor@sysoev.ru } 20320Sigor@sysoev.ru } 20420Sigor@sysoev.ru 20520Sigor@sysoev.ru return NXT_OK; 20620Sigor@sysoev.ru } 20720Sigor@sysoev.ru 20820Sigor@sysoev.ru 20920Sigor@sysoev.ru static nxt_int_t 21020Sigor@sysoev.ru nxt_runtime_systemd_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt) 21120Sigor@sysoev.ru { 21220Sigor@sysoev.ru u_char *nfd, *pid; 21320Sigor@sysoev.ru nxt_int_t n; 21420Sigor@sysoev.ru nxt_array_t *inherited_sockets; 21520Sigor@sysoev.ru nxt_socket_t s; 21620Sigor@sysoev.ru nxt_listen_socket_t *ls; 21720Sigor@sysoev.ru 21820Sigor@sysoev.ru /* 21920Sigor@sysoev.ru * Number of listening sockets passed. The socket 22020Sigor@sysoev.ru * descriptors start from number 3 and are sequential. 22120Sigor@sysoev.ru */ 22220Sigor@sysoev.ru nfd = (u_char *) getenv("LISTEN_FDS"); 22320Sigor@sysoev.ru if (nfd == NULL) { 22420Sigor@sysoev.ru return NXT_OK; 22520Sigor@sysoev.ru } 22620Sigor@sysoev.ru 22720Sigor@sysoev.ru /* The pid of the service process. */ 22820Sigor@sysoev.ru pid = (u_char *) getenv("LISTEN_PID"); 22920Sigor@sysoev.ru if (pid == NULL) { 23020Sigor@sysoev.ru return NXT_OK; 23120Sigor@sysoev.ru } 23220Sigor@sysoev.ru 23320Sigor@sysoev.ru n = nxt_int_parse(nfd, nxt_strlen(nfd)); 23420Sigor@sysoev.ru if (n < 0) { 23520Sigor@sysoev.ru return NXT_OK; 23620Sigor@sysoev.ru } 23720Sigor@sysoev.ru 23820Sigor@sysoev.ru if (nxt_pid != nxt_int_parse(pid, nxt_strlen(pid))) { 23920Sigor@sysoev.ru return NXT_OK; 24020Sigor@sysoev.ru } 24120Sigor@sysoev.ru 24220Sigor@sysoev.ru nxt_log(task, NXT_LOG_INFO, "using %s systemd listen sockets", n); 24320Sigor@sysoev.ru 24420Sigor@sysoev.ru inherited_sockets = nxt_array_create(rt->mem_pool, 24520Sigor@sysoev.ru n, sizeof(nxt_listen_socket_t)); 24620Sigor@sysoev.ru if (inherited_sockets == NULL) { 24720Sigor@sysoev.ru return NXT_ERROR; 24820Sigor@sysoev.ru } 24920Sigor@sysoev.ru 25020Sigor@sysoev.ru rt->inherited_sockets = inherited_sockets; 25120Sigor@sysoev.ru 25220Sigor@sysoev.ru for (s = 3; s < n; s++) { 25320Sigor@sysoev.ru ls = nxt_array_zero_add(inherited_sockets); 25420Sigor@sysoev.ru if (nxt_slow_path(ls == NULL)) { 25520Sigor@sysoev.ru return NXT_ERROR; 25620Sigor@sysoev.ru } 25720Sigor@sysoev.ru 25820Sigor@sysoev.ru ls->socket = s; 25920Sigor@sysoev.ru 26020Sigor@sysoev.ru ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s); 26120Sigor@sysoev.ru if (nxt_slow_path(ls->sockaddr == NULL)) { 26220Sigor@sysoev.ru return NXT_ERROR; 26320Sigor@sysoev.ru } 26420Sigor@sysoev.ru 26520Sigor@sysoev.ru ls->sockaddr->type = SOCK_STREAM; 26620Sigor@sysoev.ru } 26720Sigor@sysoev.ru 26820Sigor@sysoev.ru return NXT_OK; 26920Sigor@sysoev.ru } 27020Sigor@sysoev.ru 27120Sigor@sysoev.ru 27220Sigor@sysoev.ru static nxt_int_t 27320Sigor@sysoev.ru nxt_runtime_event_engines(nxt_task_t *task, nxt_runtime_t *rt) 27420Sigor@sysoev.ru { 27553Sigor@sysoev.ru nxt_thread_t *thread; 27653Sigor@sysoev.ru nxt_event_engine_t *engine; 27720Sigor@sysoev.ru const nxt_event_interface_t *interface; 27820Sigor@sysoev.ru 27920Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 28020Sigor@sysoev.ru 28120Sigor@sysoev.ru if (nxt_slow_path(interface == NULL)) { 28220Sigor@sysoev.ru /* TODO: log */ 28320Sigor@sysoev.ru return NXT_ERROR; 28420Sigor@sysoev.ru } 28520Sigor@sysoev.ru 28620Sigor@sysoev.ru engine = nxt_event_engine_create(task, interface, 287240Sigor@sysoev.ru nxt_main_process_signals, 0, 0); 28820Sigor@sysoev.ru 28920Sigor@sysoev.ru if (nxt_slow_path(engine == NULL)) { 29020Sigor@sysoev.ru return NXT_ERROR; 29120Sigor@sysoev.ru } 29220Sigor@sysoev.ru 29353Sigor@sysoev.ru thread = task->thread; 29453Sigor@sysoev.ru thread->engine = engine; 295326Svbart@nginx.com #if 0 29653Sigor@sysoev.ru thread->fiber = &engine->fibers->fiber; 297326Svbart@nginx.com #endif 29853Sigor@sysoev.ru 29920Sigor@sysoev.ru engine->id = rt->last_engine_id++; 300342Smax.romanov@nginx.com engine->mem_pool = nxt_mp_create(1024, 128, 256, 32); 30153Sigor@sysoev.ru 30253Sigor@sysoev.ru nxt_queue_init(&rt->engines); 30353Sigor@sysoev.ru nxt_queue_insert_tail(&rt->engines, &engine->link); 30420Sigor@sysoev.ru 30520Sigor@sysoev.ru return NXT_OK; 30620Sigor@sysoev.ru } 30720Sigor@sysoev.ru 30820Sigor@sysoev.ru 30920Sigor@sysoev.ru static nxt_int_t 31020Sigor@sysoev.ru nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt) 31120Sigor@sysoev.ru { 31220Sigor@sysoev.ru nxt_int_t ret; 31320Sigor@sysoev.ru nxt_array_t *thread_pools; 31420Sigor@sysoev.ru 31520Sigor@sysoev.ru thread_pools = nxt_array_create(rt->mem_pool, 1, 31620Sigor@sysoev.ru sizeof(nxt_thread_pool_t *)); 31720Sigor@sysoev.ru 31820Sigor@sysoev.ru if (nxt_slow_path(thread_pools == NULL)) { 31920Sigor@sysoev.ru return NXT_ERROR; 32020Sigor@sysoev.ru } 32120Sigor@sysoev.ru 32220Sigor@sysoev.ru rt->thread_pools = thread_pools; 32320Sigor@sysoev.ru ret = nxt_runtime_thread_pool_create(thr, rt, 2, 60000 * 1000000LL); 32420Sigor@sysoev.ru 32520Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 32620Sigor@sysoev.ru return NXT_ERROR; 32720Sigor@sysoev.ru } 32820Sigor@sysoev.ru 32920Sigor@sysoev.ru return NXT_OK; 33020Sigor@sysoev.ru } 33120Sigor@sysoev.ru 33220Sigor@sysoev.ru 33320Sigor@sysoev.ru static void 33420Sigor@sysoev.ru nxt_runtime_start(nxt_task_t *task, void *obj, void *data) 33520Sigor@sysoev.ru { 33620Sigor@sysoev.ru nxt_runtime_t *rt; 33720Sigor@sysoev.ru 33820Sigor@sysoev.ru rt = obj; 33920Sigor@sysoev.ru 34020Sigor@sysoev.ru nxt_debug(task, "rt conf done"); 34120Sigor@sysoev.ru 34220Sigor@sysoev.ru task->thread->log->ctx_handler = NULL; 34320Sigor@sysoev.ru task->thread->log->ctx = NULL; 34420Sigor@sysoev.ru 34520Sigor@sysoev.ru if (nxt_runtime_log_files_create(task, rt) != NXT_OK) { 34620Sigor@sysoev.ru goto fail; 34720Sigor@sysoev.ru } 34820Sigor@sysoev.ru 34920Sigor@sysoev.ru if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) { 35020Sigor@sysoev.ru goto fail; 35120Sigor@sysoev.ru } 35220Sigor@sysoev.ru 35320Sigor@sysoev.ru /* 35420Sigor@sysoev.ru * Thread pools should be destroyed before starting worker 35520Sigor@sysoev.ru * processes, because thread pool semaphores will stick in 35620Sigor@sysoev.ru * locked state in new processes after fork(). 35720Sigor@sysoev.ru */ 35820Sigor@sysoev.ru nxt_runtime_thread_pool_destroy(task, rt, rt->start); 35920Sigor@sysoev.ru 36020Sigor@sysoev.ru return; 36120Sigor@sysoev.ru 36220Sigor@sysoev.ru fail: 36320Sigor@sysoev.ru 36420Sigor@sysoev.ru nxt_runtime_quit(task); 36520Sigor@sysoev.ru } 36620Sigor@sysoev.ru 36720Sigor@sysoev.ru 36820Sigor@sysoev.ru static void 36920Sigor@sysoev.ru nxt_runtime_initial_start(nxt_task_t *task) 37020Sigor@sysoev.ru { 37120Sigor@sysoev.ru nxt_int_t ret; 37220Sigor@sysoev.ru nxt_thread_t *thr; 37320Sigor@sysoev.ru nxt_runtime_t *rt; 37420Sigor@sysoev.ru const nxt_event_interface_t *interface; 37520Sigor@sysoev.ru 37620Sigor@sysoev.ru thr = task->thread; 37720Sigor@sysoev.ru rt = thr->runtime; 37820Sigor@sysoev.ru 37920Sigor@sysoev.ru if (rt->inherited_sockets == NULL && rt->daemon) { 38020Sigor@sysoev.ru 38120Sigor@sysoev.ru if (nxt_process_daemon(task) != NXT_OK) { 38220Sigor@sysoev.ru goto fail; 38320Sigor@sysoev.ru } 38420Sigor@sysoev.ru 38520Sigor@sysoev.ru /* 38620Sigor@sysoev.ru * An event engine should be updated after fork() 38720Sigor@sysoev.ru * even if an event facility was not changed because: 38820Sigor@sysoev.ru * 1) inherited kqueue descriptor is invalid, 38920Sigor@sysoev.ru * 2) the signal thread is not inherited. 39020Sigor@sysoev.ru */ 39120Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", rt->engine); 39220Sigor@sysoev.ru if (interface == NULL) { 39320Sigor@sysoev.ru goto fail; 39420Sigor@sysoev.ru } 39520Sigor@sysoev.ru 39620Sigor@sysoev.ru ret = nxt_event_engine_change(task->thread->engine, interface, 39720Sigor@sysoev.ru rt->batch); 39820Sigor@sysoev.ru if (ret != NXT_OK) { 39920Sigor@sysoev.ru goto fail; 40020Sigor@sysoev.ru } 40120Sigor@sysoev.ru } 40220Sigor@sysoev.ru 40320Sigor@sysoev.ru ret = nxt_runtime_pid_file_create(task, rt->pid_file); 40420Sigor@sysoev.ru if (ret != NXT_OK) { 40520Sigor@sysoev.ru goto fail; 40620Sigor@sysoev.ru } 40720Sigor@sysoev.ru 40820Sigor@sysoev.ru if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) { 40920Sigor@sysoev.ru goto fail; 41020Sigor@sysoev.ru } 41120Sigor@sysoev.ru 41220Sigor@sysoev.ru thr->engine->max_connections = rt->engine_connections; 41320Sigor@sysoev.ru 414240Sigor@sysoev.ru if (rt->main_process) { 415240Sigor@sysoev.ru if (nxt_main_process_start(thr, task, rt) != NXT_ERROR) { 41620Sigor@sysoev.ru return; 41720Sigor@sysoev.ru } 41820Sigor@sysoev.ru 41920Sigor@sysoev.ru } else { 42020Sigor@sysoev.ru nxt_single_process_start(thr, task, rt); 42120Sigor@sysoev.ru return; 42220Sigor@sysoev.ru } 42320Sigor@sysoev.ru 42420Sigor@sysoev.ru fail: 42520Sigor@sysoev.ru 42620Sigor@sysoev.ru nxt_runtime_quit(task); 42720Sigor@sysoev.ru } 42820Sigor@sysoev.ru 42920Sigor@sysoev.ru 43020Sigor@sysoev.ru static void 43120Sigor@sysoev.ru nxt_single_process_start(nxt_thread_t *thr, nxt_task_t *task, nxt_runtime_t *rt) 43220Sigor@sysoev.ru { 43320Sigor@sysoev.ru nxt_int_t ret; 43420Sigor@sysoev.ru 43520Sigor@sysoev.ru ret = nxt_runtime_thread_pool_create(thr, rt, rt->auxiliary_threads, 43620Sigor@sysoev.ru 60000 * 1000000LL); 43720Sigor@sysoev.ru 43820Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 43920Sigor@sysoev.ru nxt_runtime_quit(task); 44020Sigor@sysoev.ru return; 44120Sigor@sysoev.ru } 44220Sigor@sysoev.ru 443125Smax.romanov@nginx.com rt->types |= (1U << NXT_PROCESS_SINGLE); 44420Sigor@sysoev.ru 44520Sigor@sysoev.ru nxt_runtime_listen_sockets_enable(task, rt); 44620Sigor@sysoev.ru 44720Sigor@sysoev.ru return; 44820Sigor@sysoev.ru } 44920Sigor@sysoev.ru 45020Sigor@sysoev.ru 45120Sigor@sysoev.ru void 45220Sigor@sysoev.ru nxt_runtime_quit(nxt_task_t *task) 45320Sigor@sysoev.ru { 45420Sigor@sysoev.ru nxt_bool_t done; 45520Sigor@sysoev.ru nxt_runtime_t *rt; 45620Sigor@sysoev.ru nxt_event_engine_t *engine; 45720Sigor@sysoev.ru 45820Sigor@sysoev.ru rt = task->thread->runtime; 45920Sigor@sysoev.ru engine = task->thread->engine; 46020Sigor@sysoev.ru 46120Sigor@sysoev.ru nxt_debug(task, "exiting"); 46220Sigor@sysoev.ru 46320Sigor@sysoev.ru done = 1; 46420Sigor@sysoev.ru 46520Sigor@sysoev.ru if (!engine->shutdown) { 46620Sigor@sysoev.ru engine->shutdown = 1; 46720Sigor@sysoev.ru 46820Sigor@sysoev.ru if (!nxt_array_is_empty(rt->thread_pools)) { 46920Sigor@sysoev.ru nxt_runtime_thread_pool_destroy(task, rt, nxt_runtime_quit); 47020Sigor@sysoev.ru done = 0; 47120Sigor@sysoev.ru } 47220Sigor@sysoev.ru 473240Sigor@sysoev.ru if (nxt_runtime_is_main(rt)) { 474240Sigor@sysoev.ru nxt_main_stop_worker_processes(task, rt); 47520Sigor@sysoev.ru done = 0; 47620Sigor@sysoev.ru } 47720Sigor@sysoev.ru } 47820Sigor@sysoev.ru 47920Sigor@sysoev.ru nxt_runtime_close_idle_connections(engine); 48020Sigor@sysoev.ru 48120Sigor@sysoev.ru if (done) { 48220Sigor@sysoev.ru nxt_work_queue_add(&engine->fast_work_queue, nxt_runtime_exit, 48320Sigor@sysoev.ru task, rt, engine); 48420Sigor@sysoev.ru } 48520Sigor@sysoev.ru } 48620Sigor@sysoev.ru 48720Sigor@sysoev.ru 48820Sigor@sysoev.ru static void 48920Sigor@sysoev.ru nxt_runtime_close_idle_connections(nxt_event_engine_t *engine) 49020Sigor@sysoev.ru { 49162Sigor@sysoev.ru nxt_conn_t *c; 49220Sigor@sysoev.ru nxt_queue_t *idle; 49320Sigor@sysoev.ru nxt_queue_link_t *link, *next; 49420Sigor@sysoev.ru 49520Sigor@sysoev.ru nxt_debug(&engine->task, "close idle connections"); 49620Sigor@sysoev.ru 49720Sigor@sysoev.ru idle = &engine->idle_connections; 49820Sigor@sysoev.ru 49920Sigor@sysoev.ru for (link = nxt_queue_head(idle); 50020Sigor@sysoev.ru link != nxt_queue_tail(idle); 50120Sigor@sysoev.ru link = next) 50220Sigor@sysoev.ru { 50320Sigor@sysoev.ru next = nxt_queue_next(link); 50462Sigor@sysoev.ru c = nxt_queue_link_data(link, nxt_conn_t, link); 50520Sigor@sysoev.ru 50620Sigor@sysoev.ru if (!c->socket.read_ready) { 50720Sigor@sysoev.ru nxt_queue_remove(link); 50862Sigor@sysoev.ru nxt_conn_close(engine, c); 50920Sigor@sysoev.ru } 51020Sigor@sysoev.ru } 51120Sigor@sysoev.ru } 51220Sigor@sysoev.ru 51320Sigor@sysoev.ru 51420Sigor@sysoev.ru static void 51520Sigor@sysoev.ru nxt_runtime_exit(nxt_task_t *task, void *obj, void *data) 51620Sigor@sysoev.ru { 517125Smax.romanov@nginx.com nxt_runtime_t *rt; 518125Smax.romanov@nginx.com nxt_process_t *process; 51920Sigor@sysoev.ru nxt_event_engine_t *engine; 52020Sigor@sysoev.ru 52120Sigor@sysoev.ru rt = obj; 52220Sigor@sysoev.ru engine = data; 52320Sigor@sysoev.ru 52420Sigor@sysoev.ru nxt_debug(task, "thread pools: %d", rt->thread_pools->nelts); 52520Sigor@sysoev.ru 52620Sigor@sysoev.ru if (!nxt_array_is_empty(rt->thread_pools)) { 52720Sigor@sysoev.ru return; 52820Sigor@sysoev.ru } 52920Sigor@sysoev.ru 530240Sigor@sysoev.ru if (nxt_runtime_is_main(rt)) { 53120Sigor@sysoev.ru if (rt->pid_file != NULL) { 53220Sigor@sysoev.ru nxt_file_delete(rt->pid_file); 53320Sigor@sysoev.ru } 534234Sigor@sysoev.ru 535234Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 536234Sigor@sysoev.ru { 537234Sigor@sysoev.ru nxt_sockaddr_t *sa; 538234Sigor@sysoev.ru nxt_file_name_t *name; 539234Sigor@sysoev.ru 540234Sigor@sysoev.ru sa = rt->controller_listen; 541234Sigor@sysoev.ru 542234Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_UNIX) { 543234Sigor@sysoev.ru name = (nxt_file_name_t *) sa->u.sockaddr_un.sun_path; 544234Sigor@sysoev.ru (void) nxt_file_delete(name); 545234Sigor@sysoev.ru } 546234Sigor@sysoev.ru } 547234Sigor@sysoev.ru #endif 54820Sigor@sysoev.ru } 54920Sigor@sysoev.ru 55020Sigor@sysoev.ru if (!engine->event.signal_support) { 55120Sigor@sysoev.ru nxt_event_engine_signals_stop(engine); 55220Sigor@sysoev.ru } 55320Sigor@sysoev.ru 554125Smax.romanov@nginx.com nxt_runtime_process_each(rt, process) { 555125Smax.romanov@nginx.com 556349Smax.romanov@nginx.com nxt_process_close_ports(task, process); 557125Smax.romanov@nginx.com 558125Smax.romanov@nginx.com } nxt_runtime_process_loop; 559125Smax.romanov@nginx.com 560196Smax.romanov@nginx.com nxt_thread_mutex_destroy(&rt->processes_mutex); 561196Smax.romanov@nginx.com 562125Smax.romanov@nginx.com nxt_mp_destroy(rt->mem_pool); 563125Smax.romanov@nginx.com 56420Sigor@sysoev.ru nxt_debug(task, "exit"); 56520Sigor@sysoev.ru 56620Sigor@sysoev.ru exit(0); 56720Sigor@sysoev.ru nxt_unreachable(); 56820Sigor@sysoev.ru } 56920Sigor@sysoev.ru 57020Sigor@sysoev.ru 57120Sigor@sysoev.ru static nxt_int_t 57220Sigor@sysoev.ru nxt_runtime_event_engine_change(nxt_task_t *task, nxt_runtime_t *rt) 57320Sigor@sysoev.ru { 57420Sigor@sysoev.ru nxt_event_engine_t *engine; 57520Sigor@sysoev.ru const nxt_event_interface_t *interface; 57620Sigor@sysoev.ru 57720Sigor@sysoev.ru engine = task->thread->engine; 57820Sigor@sysoev.ru 57920Sigor@sysoev.ru if (engine->batch == rt->batch 58020Sigor@sysoev.ru && nxt_strcmp(engine->event.name, rt->engine) == 0) 58120Sigor@sysoev.ru { 58220Sigor@sysoev.ru return NXT_OK; 58320Sigor@sysoev.ru } 58420Sigor@sysoev.ru 58520Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", rt->engine); 58620Sigor@sysoev.ru 58720Sigor@sysoev.ru if (interface != NULL) { 58820Sigor@sysoev.ru return nxt_event_engine_change(engine, interface, rt->batch); 58920Sigor@sysoev.ru } 59020Sigor@sysoev.ru 59120Sigor@sysoev.ru return NXT_ERROR; 59220Sigor@sysoev.ru } 59320Sigor@sysoev.ru 59420Sigor@sysoev.ru 59520Sigor@sysoev.ru void 59620Sigor@sysoev.ru nxt_runtime_event_engine_free(nxt_runtime_t *rt) 59720Sigor@sysoev.ru { 59853Sigor@sysoev.ru nxt_queue_link_t *link; 59953Sigor@sysoev.ru nxt_event_engine_t *engine; 60020Sigor@sysoev.ru 60153Sigor@sysoev.ru link = nxt_queue_first(&rt->engines); 60253Sigor@sysoev.ru nxt_queue_remove(link); 60320Sigor@sysoev.ru 60453Sigor@sysoev.ru engine = nxt_queue_link_data(link, nxt_event_engine_t, link); 60520Sigor@sysoev.ru nxt_event_engine_free(engine); 60620Sigor@sysoev.ru } 60720Sigor@sysoev.ru 60820Sigor@sysoev.ru 60920Sigor@sysoev.ru nxt_int_t 61020Sigor@sysoev.ru nxt_runtime_thread_pool_create(nxt_thread_t *thr, nxt_runtime_t *rt, 61120Sigor@sysoev.ru nxt_uint_t max_threads, nxt_nsec_t timeout) 61220Sigor@sysoev.ru { 61320Sigor@sysoev.ru nxt_thread_pool_t *thread_pool, **tp; 61420Sigor@sysoev.ru 61520Sigor@sysoev.ru tp = nxt_array_add(rt->thread_pools); 61620Sigor@sysoev.ru if (tp == NULL) { 61720Sigor@sysoev.ru return NXT_ERROR; 61820Sigor@sysoev.ru } 61920Sigor@sysoev.ru 62020Sigor@sysoev.ru thread_pool = nxt_thread_pool_create(max_threads, timeout, 62120Sigor@sysoev.ru nxt_runtime_thread_pool_init, 62220Sigor@sysoev.ru thr->engine, 62320Sigor@sysoev.ru nxt_runtime_thread_pool_exit); 62420Sigor@sysoev.ru 62520Sigor@sysoev.ru if (nxt_fast_path(thread_pool != NULL)) { 62620Sigor@sysoev.ru *tp = thread_pool; 62720Sigor@sysoev.ru } 62820Sigor@sysoev.ru 62920Sigor@sysoev.ru return NXT_OK; 63020Sigor@sysoev.ru } 63120Sigor@sysoev.ru 63220Sigor@sysoev.ru 63320Sigor@sysoev.ru static void 63420Sigor@sysoev.ru nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt, 63520Sigor@sysoev.ru nxt_runtime_cont_t cont) 63620Sigor@sysoev.ru { 63720Sigor@sysoev.ru nxt_uint_t n; 63820Sigor@sysoev.ru nxt_thread_pool_t **tp; 63920Sigor@sysoev.ru 64020Sigor@sysoev.ru rt->continuation = cont; 64120Sigor@sysoev.ru 64220Sigor@sysoev.ru n = rt->thread_pools->nelts; 64320Sigor@sysoev.ru 64420Sigor@sysoev.ru if (n == 0) { 64520Sigor@sysoev.ru cont(task); 64620Sigor@sysoev.ru return; 64720Sigor@sysoev.ru } 64820Sigor@sysoev.ru 64920Sigor@sysoev.ru tp = rt->thread_pools->elts; 65020Sigor@sysoev.ru 65120Sigor@sysoev.ru do { 65220Sigor@sysoev.ru nxt_thread_pool_destroy(*tp); 65320Sigor@sysoev.ru 65420Sigor@sysoev.ru tp++; 65520Sigor@sysoev.ru n--; 65620Sigor@sysoev.ru } while (n != 0); 65720Sigor@sysoev.ru } 65820Sigor@sysoev.ru 65920Sigor@sysoev.ru 66020Sigor@sysoev.ru static void 66120Sigor@sysoev.ru nxt_runtime_thread_pool_init(void) 66220Sigor@sysoev.ru { 66320Sigor@sysoev.ru #if (NXT_REGEX) 66420Sigor@sysoev.ru nxt_regex_init(0); 66520Sigor@sysoev.ru #endif 66620Sigor@sysoev.ru } 66720Sigor@sysoev.ru 66820Sigor@sysoev.ru 66920Sigor@sysoev.ru static void 67020Sigor@sysoev.ru nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj, void *data) 67120Sigor@sysoev.ru { 67220Sigor@sysoev.ru nxt_uint_t i, n; 67320Sigor@sysoev.ru nxt_runtime_t *rt; 67420Sigor@sysoev.ru nxt_thread_pool_t *tp, **thread_pools; 67520Sigor@sysoev.ru nxt_thread_handle_t handle; 67620Sigor@sysoev.ru 67720Sigor@sysoev.ru tp = obj; 67820Sigor@sysoev.ru 67920Sigor@sysoev.ru if (data != NULL) { 68020Sigor@sysoev.ru handle = (nxt_thread_handle_t) (uintptr_t) data; 68120Sigor@sysoev.ru nxt_thread_wait(handle); 68220Sigor@sysoev.ru } 68320Sigor@sysoev.ru 68420Sigor@sysoev.ru rt = task->thread->runtime; 68520Sigor@sysoev.ru 68620Sigor@sysoev.ru thread_pools = rt->thread_pools->elts; 68720Sigor@sysoev.ru n = rt->thread_pools->nelts; 68820Sigor@sysoev.ru 68920Sigor@sysoev.ru nxt_debug(task, "thread pools: %ui", n); 69020Sigor@sysoev.ru 69120Sigor@sysoev.ru for (i = 0; i < n; i++) { 69220Sigor@sysoev.ru 69320Sigor@sysoev.ru if (tp == thread_pools[i]) { 69420Sigor@sysoev.ru nxt_array_remove(rt->thread_pools, &thread_pools[i]); 69520Sigor@sysoev.ru 69620Sigor@sysoev.ru if (n == 1) { 69720Sigor@sysoev.ru /* The last thread pool. */ 69820Sigor@sysoev.ru rt->continuation(task); 69920Sigor@sysoev.ru } 70020Sigor@sysoev.ru 70120Sigor@sysoev.ru return; 70220Sigor@sysoev.ru } 70320Sigor@sysoev.ru } 70420Sigor@sysoev.ru } 70520Sigor@sysoev.ru 70620Sigor@sysoev.ru 70720Sigor@sysoev.ru static nxt_int_t 70820Sigor@sysoev.ru nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt) 70920Sigor@sysoev.ru { 71020Sigor@sysoev.ru nxt_int_t ret; 711251Sigor@sysoev.ru nxt_str_t control; 712251Sigor@sysoev.ru nxt_uint_t n; 71320Sigor@sysoev.ru nxt_file_t *file; 714251Sigor@sysoev.ru const char *slash; 715234Sigor@sysoev.ru nxt_sockaddr_t *sa; 71620Sigor@sysoev.ru nxt_file_name_str_t file_name; 71720Sigor@sysoev.ru const nxt_event_interface_t *interface; 71820Sigor@sysoev.ru 71920Sigor@sysoev.ru rt->daemon = 1; 720240Sigor@sysoev.ru rt->main_process = 1; 72120Sigor@sysoev.ru rt->engine_connections = 256; 72220Sigor@sysoev.ru rt->auxiliary_threads = 2; 723232Sigor@sysoev.ru rt->user_cred.user = NXT_USER; 724232Sigor@sysoev.ru rt->group = NXT_GROUP; 725231Sigor@sysoev.ru rt->pid = NXT_PID; 726230Sigor@sysoev.ru rt->log = NXT_LOG; 727233Sigor@sysoev.ru rt->modules = NXT_MODULES; 728314Svbart@nginx.com rt->state = NXT_STATE; 729234Sigor@sysoev.ru rt->control = NXT_CONTROL_SOCK; 73020Sigor@sysoev.ru 73120Sigor@sysoev.ru if (nxt_runtime_conf_read_cmd(task, rt) != NXT_OK) { 73220Sigor@sysoev.ru return NXT_ERROR; 73320Sigor@sysoev.ru } 73420Sigor@sysoev.ru 73520Sigor@sysoev.ru if (nxt_user_cred_get(task, &rt->user_cred, rt->group) != NXT_OK) { 73620Sigor@sysoev.ru return NXT_ERROR; 73720Sigor@sysoev.ru } 73820Sigor@sysoev.ru 73920Sigor@sysoev.ru /* An engine's parameters. */ 74020Sigor@sysoev.ru 74120Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", rt->engine); 74220Sigor@sysoev.ru if (interface == NULL) { 74320Sigor@sysoev.ru return NXT_ERROR; 74420Sigor@sysoev.ru } 74520Sigor@sysoev.ru 74620Sigor@sysoev.ru rt->engine = interface->name; 74720Sigor@sysoev.ru 748252Smax.romanov@nginx.com ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->pid); 74920Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 75020Sigor@sysoev.ru return NXT_ERROR; 75120Sigor@sysoev.ru } 75220Sigor@sysoev.ru 75320Sigor@sysoev.ru rt->pid_file = file_name.start; 75420Sigor@sysoev.ru 755230Sigor@sysoev.ru ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%Z", rt->log); 75620Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 75720Sigor@sysoev.ru return NXT_ERROR; 75820Sigor@sysoev.ru } 75920Sigor@sysoev.ru 76020Sigor@sysoev.ru file = nxt_list_first(rt->log_files); 76120Sigor@sysoev.ru file->name = file_name.start; 76220Sigor@sysoev.ru 763251Sigor@sysoev.ru slash = ""; 764251Sigor@sysoev.ru n = nxt_strlen(rt->modules); 765251Sigor@sysoev.ru 766251Sigor@sysoev.ru if (n > 1 && rt->modules[n - 1] != '/') { 767251Sigor@sysoev.ru slash = "/"; 768251Sigor@sysoev.ru } 769251Sigor@sysoev.ru 770260Sigor@sysoev.ru ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%s*.unit.so%Z", 771251Sigor@sysoev.ru rt->modules, slash); 772233Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 773233Sigor@sysoev.ru return NXT_ERROR; 774233Sigor@sysoev.ru } 775233Sigor@sysoev.ru 776233Sigor@sysoev.ru rt->modules = (char *) file_name.start; 777233Sigor@sysoev.ru 778314Svbart@nginx.com slash = ""; 779314Svbart@nginx.com n = nxt_strlen(rt->state); 780314Svbart@nginx.com 781314Svbart@nginx.com if (n > 1 && rt->state[n - 1] != '/') { 782314Svbart@nginx.com slash = "/"; 783314Svbart@nginx.com } 784314Svbart@nginx.com 785314Svbart@nginx.com ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s%sconf.json%Z", 786314Svbart@nginx.com rt->state, slash); 787314Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 788314Svbart@nginx.com return NXT_ERROR; 789314Svbart@nginx.com } 790314Svbart@nginx.com 791314Svbart@nginx.com rt->conf = (char *) file_name.start; 792314Svbart@nginx.com 793314Svbart@nginx.com ret = nxt_file_name_create(rt->mem_pool, &file_name, "%s.tmp%Z", rt->conf); 794314Svbart@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 795314Svbart@nginx.com return NXT_ERROR; 796314Svbart@nginx.com } 797314Svbart@nginx.com 798314Svbart@nginx.com rt->conf_tmp = (char *) file_name.start; 799314Svbart@nginx.com 800234Sigor@sysoev.ru control.length = nxt_strlen(rt->control); 801234Sigor@sysoev.ru control.start = (u_char *) rt->control; 802234Sigor@sysoev.ru 803234Sigor@sysoev.ru sa = nxt_runtime_sockaddr_parse(task, rt->mem_pool, &control); 804234Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) { 805234Sigor@sysoev.ru return NXT_ERROR; 806234Sigor@sysoev.ru } 807234Sigor@sysoev.ru 808234Sigor@sysoev.ru rt->controller_listen = sa; 809234Sigor@sysoev.ru 810234Sigor@sysoev.ru if (nxt_runtime_controller_socket(task, rt) != NXT_OK) { 811234Sigor@sysoev.ru return NXT_ERROR; 812234Sigor@sysoev.ru } 813234Sigor@sysoev.ru 81420Sigor@sysoev.ru return NXT_OK; 81520Sigor@sysoev.ru } 81620Sigor@sysoev.ru 81720Sigor@sysoev.ru 81820Sigor@sysoev.ru static nxt_int_t 81920Sigor@sysoev.ru nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt) 82020Sigor@sysoev.ru { 821234Sigor@sysoev.ru char *p, **argv; 822234Sigor@sysoev.ru u_char *end; 823234Sigor@sysoev.ru u_char buf[1024]; 82420Sigor@sysoev.ru 825226Svbart@nginx.com static const char version[] = 826259Sigor@sysoev.ru "unit version: " NXT_VERSION "\n" 827221Sigor@sysoev.ru "configured as ./configure" NXT_CONFIGURE_OPTIONS "\n"; 828221Sigor@sysoev.ru 829234Sigor@sysoev.ru static const char no_control[] = 830234Sigor@sysoev.ru "option \"--control\" requires socket address\n"; 831232Sigor@sysoev.ru static const char no_user[] = "option \"--user\" requires username\n"; 832232Sigor@sysoev.ru static const char no_group[] = "option \"--group\" requires group name\n"; 833231Sigor@sysoev.ru static const char no_pid[] = "option \"--pid\" requires filename\n"; 834230Sigor@sysoev.ru static const char no_log[] = "option \"--log\" requires filename\n"; 835233Sigor@sysoev.ru static const char no_modules[] = 836233Sigor@sysoev.ru "option \"--modules\" requires directory\n"; 837314Svbart@nginx.com static const char no_state[] = "option \"--state\" requires directory\n"; 838230Sigor@sysoev.ru 839235Sigor@sysoev.ru static const char help[] = 840235Sigor@sysoev.ru "\n" 841259Sigor@sysoev.ru "unit options:\n" 842235Sigor@sysoev.ru "\n" 843259Sigor@sysoev.ru " --version print unit version and configure options\n" 844235Sigor@sysoev.ru "\n" 845259Sigor@sysoev.ru " --no-daemon run unit in non-daemon mode\n" 846235Sigor@sysoev.ru "\n" 847235Sigor@sysoev.ru " --control ADDRESS set address of control API socket\n" 848235Sigor@sysoev.ru " default: \"" NXT_CONTROL_SOCK "\"\n" 849235Sigor@sysoev.ru "\n" 850239Sigor@sysoev.ru " --pid FILE set pid filename\n" 851235Sigor@sysoev.ru " default: \"" NXT_PID "\"\n" 852235Sigor@sysoev.ru "\n" 853239Sigor@sysoev.ru " --log FILE set log filename\n" 854235Sigor@sysoev.ru " default: \"" NXT_LOG "\"\n" 855235Sigor@sysoev.ru "\n" 856239Sigor@sysoev.ru " --modules DIRECTORY set modules directory name\n" 857235Sigor@sysoev.ru " default: \"" NXT_MODULES "\"\n" 858235Sigor@sysoev.ru "\n" 859314Svbart@nginx.com " --state DIRECTORY set state directory name\n" 860314Svbart@nginx.com " default: \"" NXT_STATE "\"\n" 861314Svbart@nginx.com "\n" 862235Sigor@sysoev.ru " --user USER set non-privileged processes to run" 863235Sigor@sysoev.ru " as specified user\n" 864235Sigor@sysoev.ru " default: \"" NXT_USER "\"\n" 865235Sigor@sysoev.ru "\n" 866235Sigor@sysoev.ru " --group GROUP set non-privileged processes to run" 867235Sigor@sysoev.ru " as specified group\n" 868235Sigor@sysoev.ru " default: "; 869235Sigor@sysoev.ru 870235Sigor@sysoev.ru static const char group[] = "\"" NXT_GROUP "\"\n\n"; 871235Sigor@sysoev.ru static const char primary[] = "user's primary group\n\n"; 872235Sigor@sysoev.ru 873222Sigor@sysoev.ru argv = &nxt_process_argv[1]; 87420Sigor@sysoev.ru 87520Sigor@sysoev.ru while (*argv != NULL) { 87620Sigor@sysoev.ru p = *argv++; 87720Sigor@sysoev.ru 878234Sigor@sysoev.ru if (nxt_strcmp(p, "--control") == 0) { 87920Sigor@sysoev.ru if (*argv == NULL) { 880234Sigor@sysoev.ru write(STDERR_FILENO, no_control, sizeof(no_control) - 1); 88120Sigor@sysoev.ru return NXT_ERROR; 88220Sigor@sysoev.ru } 88320Sigor@sysoev.ru 88420Sigor@sysoev.ru p = *argv++; 88520Sigor@sysoev.ru 886234Sigor@sysoev.ru rt->control = p; 88720Sigor@sysoev.ru 88820Sigor@sysoev.ru continue; 88920Sigor@sysoev.ru } 89020Sigor@sysoev.ru 89120Sigor@sysoev.ru if (nxt_strcmp(p, "--upstream") == 0) { 89220Sigor@sysoev.ru if (*argv == NULL) { 89320Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 89420Sigor@sysoev.ru "no argument for option \"--upstream\""); 89520Sigor@sysoev.ru return NXT_ERROR; 89620Sigor@sysoev.ru } 89720Sigor@sysoev.ru 89820Sigor@sysoev.ru p = *argv++; 89920Sigor@sysoev.ru 90020Sigor@sysoev.ru rt->upstream.length = nxt_strlen(p); 90120Sigor@sysoev.ru rt->upstream.start = (u_char *) p; 90220Sigor@sysoev.ru 90320Sigor@sysoev.ru continue; 90420Sigor@sysoev.ru } 90520Sigor@sysoev.ru 90620Sigor@sysoev.ru if (nxt_strcmp(p, "--user") == 0) { 90720Sigor@sysoev.ru if (*argv == NULL) { 908232Sigor@sysoev.ru write(STDERR_FILENO, no_user, sizeof(no_user) - 1); 90920Sigor@sysoev.ru return NXT_ERROR; 91020Sigor@sysoev.ru } 91120Sigor@sysoev.ru 91220Sigor@sysoev.ru p = *argv++; 91320Sigor@sysoev.ru 91420Sigor@sysoev.ru rt->user_cred.user = p; 91520Sigor@sysoev.ru 91620Sigor@sysoev.ru continue; 91720Sigor@sysoev.ru } 91820Sigor@sysoev.ru 91920Sigor@sysoev.ru if (nxt_strcmp(p, "--group") == 0) { 92020Sigor@sysoev.ru if (*argv == NULL) { 921232Sigor@sysoev.ru write(STDERR_FILENO, no_group, sizeof(no_group) - 1); 92220Sigor@sysoev.ru return NXT_ERROR; 92320Sigor@sysoev.ru } 92420Sigor@sysoev.ru 92520Sigor@sysoev.ru p = *argv++; 92620Sigor@sysoev.ru 92720Sigor@sysoev.ru rt->group = p; 92820Sigor@sysoev.ru 92920Sigor@sysoev.ru continue; 93020Sigor@sysoev.ru } 93120Sigor@sysoev.ru 93220Sigor@sysoev.ru if (nxt_strcmp(p, "--pid") == 0) { 93320Sigor@sysoev.ru if (*argv == NULL) { 934231Sigor@sysoev.ru write(STDERR_FILENO, no_pid, sizeof(no_pid) - 1); 93520Sigor@sysoev.ru return NXT_ERROR; 93620Sigor@sysoev.ru } 93720Sigor@sysoev.ru 93820Sigor@sysoev.ru p = *argv++; 93920Sigor@sysoev.ru 94020Sigor@sysoev.ru rt->pid = p; 94120Sigor@sysoev.ru 94220Sigor@sysoev.ru continue; 94320Sigor@sysoev.ru } 94420Sigor@sysoev.ru 94520Sigor@sysoev.ru if (nxt_strcmp(p, "--log") == 0) { 94620Sigor@sysoev.ru if (*argv == NULL) { 947230Sigor@sysoev.ru write(STDERR_FILENO, no_log, sizeof(no_log) - 1); 94820Sigor@sysoev.ru return NXT_ERROR; 94920Sigor@sysoev.ru } 95020Sigor@sysoev.ru 95120Sigor@sysoev.ru p = *argv++; 95220Sigor@sysoev.ru 953230Sigor@sysoev.ru rt->log = p; 95420Sigor@sysoev.ru 95520Sigor@sysoev.ru continue; 95620Sigor@sysoev.ru } 95720Sigor@sysoev.ru 958233Sigor@sysoev.ru if (nxt_strcmp(p, "--modules") == 0) { 959233Sigor@sysoev.ru if (*argv == NULL) { 960233Sigor@sysoev.ru write(STDERR_FILENO, no_modules, sizeof(no_modules) - 1); 961233Sigor@sysoev.ru return NXT_ERROR; 962233Sigor@sysoev.ru } 963233Sigor@sysoev.ru 964233Sigor@sysoev.ru p = *argv++; 965233Sigor@sysoev.ru 966233Sigor@sysoev.ru rt->modules = p; 967233Sigor@sysoev.ru 968233Sigor@sysoev.ru continue; 969233Sigor@sysoev.ru } 970233Sigor@sysoev.ru 971314Svbart@nginx.com if (nxt_strcmp(p, "--state") == 0) { 972314Svbart@nginx.com if (*argv == NULL) { 973314Svbart@nginx.com write(STDERR_FILENO, no_state, sizeof(no_state) - 1); 974314Svbart@nginx.com return NXT_ERROR; 975314Svbart@nginx.com } 976314Svbart@nginx.com 977314Svbart@nginx.com p = *argv++; 978314Svbart@nginx.com 979314Svbart@nginx.com rt->state = p; 980314Svbart@nginx.com 981314Svbart@nginx.com continue; 982314Svbart@nginx.com } 983314Svbart@nginx.com 984219Sigor@sysoev.ru if (nxt_strcmp(p, "--no-daemon") == 0) { 98520Sigor@sysoev.ru rt->daemon = 0; 98620Sigor@sysoev.ru continue; 98720Sigor@sysoev.ru } 988221Sigor@sysoev.ru 989221Sigor@sysoev.ru if (nxt_strcmp(p, "--version") == 0) { 990221Sigor@sysoev.ru write(STDERR_FILENO, version, sizeof(version) - 1); 991221Sigor@sysoev.ru exit(0); 992221Sigor@sysoev.ru } 993222Sigor@sysoev.ru 994235Sigor@sysoev.ru if (nxt_strcmp(p, "--help") == 0) { 995235Sigor@sysoev.ru write(STDOUT_FILENO, help, sizeof(help) - 1); 996235Sigor@sysoev.ru 997235Sigor@sysoev.ru if (sizeof(NXT_GROUP) == 1) { 998235Sigor@sysoev.ru write(STDOUT_FILENO, primary, sizeof(primary) - 1); 999235Sigor@sysoev.ru 1000235Sigor@sysoev.ru } else { 1001235Sigor@sysoev.ru write(STDOUT_FILENO, group, sizeof(group) - 1); 1002235Sigor@sysoev.ru } 1003235Sigor@sysoev.ru 1004235Sigor@sysoev.ru exit(0); 1005235Sigor@sysoev.ru } 1006235Sigor@sysoev.ru 1007222Sigor@sysoev.ru end = nxt_sprintf(buf, buf + sizeof(buf), "unknown option \"%s\"\n", p); 1008222Sigor@sysoev.ru write(STDERR_FILENO, buf, end - buf); 1009222Sigor@sysoev.ru 1010222Sigor@sysoev.ru return NXT_ERROR; 101120Sigor@sysoev.ru } 101220Sigor@sysoev.ru 101320Sigor@sysoev.ru return NXT_OK; 101420Sigor@sysoev.ru } 101520Sigor@sysoev.ru 101620Sigor@sysoev.ru 101720Sigor@sysoev.ru static nxt_sockaddr_t * 101865Sigor@sysoev.ru nxt_runtime_sockaddr_parse(nxt_task_t *task, nxt_mp_t *mp, nxt_str_t *addr) 101920Sigor@sysoev.ru { 102020Sigor@sysoev.ru u_char *p; 102120Sigor@sysoev.ru size_t length; 102220Sigor@sysoev.ru 102320Sigor@sysoev.ru length = addr->length; 102420Sigor@sysoev.ru p = addr->start; 102520Sigor@sysoev.ru 102671Svbart@nginx.com if (length >= 5 && nxt_memcmp(p, "unix:", 5) == 0) { 102720Sigor@sysoev.ru return nxt_runtime_sockaddr_unix_parse(task, mp, addr); 102820Sigor@sysoev.ru } 102920Sigor@sysoev.ru 103020Sigor@sysoev.ru if (length != 0 && *p == '[') { 103120Sigor@sysoev.ru return nxt_runtime_sockaddr_inet6_parse(task, mp, addr); 103220Sigor@sysoev.ru } 103320Sigor@sysoev.ru 103420Sigor@sysoev.ru return nxt_runtime_sockaddr_inet_parse(task, mp, addr); 103520Sigor@sysoev.ru } 103620Sigor@sysoev.ru 103720Sigor@sysoev.ru 103820Sigor@sysoev.ru static nxt_sockaddr_t * 103965Sigor@sysoev.ru nxt_runtime_sockaddr_unix_parse(nxt_task_t *task, nxt_mp_t *mp, nxt_str_t *addr) 104020Sigor@sysoev.ru { 104120Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 104220Sigor@sysoev.ru u_char *p; 104320Sigor@sysoev.ru size_t length, socklen; 104420Sigor@sysoev.ru nxt_sockaddr_t *sa; 104520Sigor@sysoev.ru 104620Sigor@sysoev.ru /* 104720Sigor@sysoev.ru * Actual sockaddr_un length can be lesser or even larger than defined 1048211Sru@nginx.com * struct sockaddr_un length (see comment in nxt_socket.h). So 104920Sigor@sysoev.ru * limit maximum Unix domain socket address length by defined sun_path[] 105020Sigor@sysoev.ru * length because some OSes accept addresses twice larger than defined 105120Sigor@sysoev.ru * struct sockaddr_un. Also reserve space for a trailing zero to avoid 105220Sigor@sysoev.ru * ambiguity, since many OSes accept Unix domain socket addresses 105320Sigor@sysoev.ru * without a trailing zero. 105420Sigor@sysoev.ru */ 105520Sigor@sysoev.ru const size_t max_len = sizeof(struct sockaddr_un) 105620Sigor@sysoev.ru - offsetof(struct sockaddr_un, sun_path) - 1; 105720Sigor@sysoev.ru 105820Sigor@sysoev.ru /* cutting "unix:" */ 105920Sigor@sysoev.ru length = addr->length - 5; 106020Sigor@sysoev.ru p = addr->start + 5; 106120Sigor@sysoev.ru 106220Sigor@sysoev.ru if (length == 0) { 106320Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 106420Sigor@sysoev.ru "unix domain socket \"%V\" name is invalid", addr); 106520Sigor@sysoev.ru return NULL; 106620Sigor@sysoev.ru } 106720Sigor@sysoev.ru 106820Sigor@sysoev.ru if (length > max_len) { 106920Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 107020Sigor@sysoev.ru "unix domain socket \"%V\" name is too long", addr); 107120Sigor@sysoev.ru return NULL; 107220Sigor@sysoev.ru } 107320Sigor@sysoev.ru 107420Sigor@sysoev.ru socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; 107520Sigor@sysoev.ru 107620Sigor@sysoev.ru #if (NXT_LINUX) 107720Sigor@sysoev.ru 107820Sigor@sysoev.ru /* 107920Sigor@sysoev.ru * Linux unix(7): 108020Sigor@sysoev.ru * 108120Sigor@sysoev.ru * abstract: an abstract socket address is distinguished by the fact 108220Sigor@sysoev.ru * that sun_path[0] is a null byte ('\0'). The socket's address in 108320Sigor@sysoev.ru * this namespace is given by the additional bytes in sun_path that 108420Sigor@sysoev.ru * are covered by the specified length of the address structure. 108520Sigor@sysoev.ru * (Null bytes in the name have no special significance.) 108620Sigor@sysoev.ru */ 108720Sigor@sysoev.ru if (p[0] == '@') { 108820Sigor@sysoev.ru p[0] = '\0'; 108920Sigor@sysoev.ru socklen--; 109020Sigor@sysoev.ru } 109120Sigor@sysoev.ru 109220Sigor@sysoev.ru #endif 109320Sigor@sysoev.ru 109420Sigor@sysoev.ru sa = nxt_sockaddr_alloc(mp, socklen, addr->length); 109520Sigor@sysoev.ru 109620Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) { 109720Sigor@sysoev.ru return NULL; 109820Sigor@sysoev.ru } 109920Sigor@sysoev.ru 110020Sigor@sysoev.ru sa->type = SOCK_STREAM; 110120Sigor@sysoev.ru 110220Sigor@sysoev.ru sa->u.sockaddr_un.sun_family = AF_UNIX; 110320Sigor@sysoev.ru nxt_memcpy(sa->u.sockaddr_un.sun_path, p, length); 110420Sigor@sysoev.ru 110520Sigor@sysoev.ru return sa; 110620Sigor@sysoev.ru 110720Sigor@sysoev.ru #else /* !(NXT_HAVE_UNIX_DOMAIN) */ 110820Sigor@sysoev.ru 110920Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unix domain socket \"%V\" is not supported", 111020Sigor@sysoev.ru addr); 111120Sigor@sysoev.ru 111220Sigor@sysoev.ru return NULL; 111320Sigor@sysoev.ru 111420Sigor@sysoev.ru #endif 111520Sigor@sysoev.ru } 111620Sigor@sysoev.ru 111720Sigor@sysoev.ru 111820Sigor@sysoev.ru static nxt_sockaddr_t * 111965Sigor@sysoev.ru nxt_runtime_sockaddr_inet6_parse(nxt_task_t *task, nxt_mp_t *mp, 112020Sigor@sysoev.ru nxt_str_t *addr) 112120Sigor@sysoev.ru { 112220Sigor@sysoev.ru #if (NXT_INET6) 1123105Sigor@sysoev.ru u_char *p, *addr_end; 112420Sigor@sysoev.ru size_t length; 112520Sigor@sysoev.ru nxt_int_t port; 112620Sigor@sysoev.ru nxt_sockaddr_t *sa; 112720Sigor@sysoev.ru struct in6_addr *in6_addr; 112820Sigor@sysoev.ru 112920Sigor@sysoev.ru length = addr->length - 1; 113020Sigor@sysoev.ru p = addr->start + 1; 113120Sigor@sysoev.ru 113220Sigor@sysoev.ru addr_end = nxt_memchr(p, ']', length); 113320Sigor@sysoev.ru 113420Sigor@sysoev.ru if (addr_end == NULL) { 113520Sigor@sysoev.ru goto invalid_address; 113620Sigor@sysoev.ru } 113720Sigor@sysoev.ru 1138105Sigor@sysoev.ru sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6), 1139105Sigor@sysoev.ru NXT_INET6_ADDR_STR_LEN); 114020Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) { 114120Sigor@sysoev.ru return NULL; 114220Sigor@sysoev.ru } 114320Sigor@sysoev.ru 114420Sigor@sysoev.ru in6_addr = &sa->u.sockaddr_in6.sin6_addr; 114520Sigor@sysoev.ru 114620Sigor@sysoev.ru if (nxt_inet6_addr(in6_addr, p, addr_end - p) != NXT_OK) { 114720Sigor@sysoev.ru goto invalid_address; 114820Sigor@sysoev.ru } 114920Sigor@sysoev.ru 1150105Sigor@sysoev.ru port = 0; 115120Sigor@sysoev.ru p = addr_end + 1; 115220Sigor@sysoev.ru length = (p + length) - p; 115320Sigor@sysoev.ru 115420Sigor@sysoev.ru if (length == 0) { 115520Sigor@sysoev.ru goto found; 115620Sigor@sysoev.ru } 115720Sigor@sysoev.ru 115820Sigor@sysoev.ru if (*p == ':') { 115920Sigor@sysoev.ru port = nxt_int_parse(p + 1, length - 1); 116020Sigor@sysoev.ru 116120Sigor@sysoev.ru if (port >= 1 && port <= 65535) { 116220Sigor@sysoev.ru goto found; 116320Sigor@sysoev.ru } 116420Sigor@sysoev.ru } 116520Sigor@sysoev.ru 116620Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid port in \"%V\"", addr); 116720Sigor@sysoev.ru 116820Sigor@sysoev.ru return NULL; 116920Sigor@sysoev.ru 117020Sigor@sysoev.ru found: 117120Sigor@sysoev.ru 117220Sigor@sysoev.ru sa->type = SOCK_STREAM; 117320Sigor@sysoev.ru 117420Sigor@sysoev.ru sa->u.sockaddr_in6.sin6_family = AF_INET6; 117520Sigor@sysoev.ru sa->u.sockaddr_in6.sin6_port = htons((in_port_t) port); 117620Sigor@sysoev.ru 117720Sigor@sysoev.ru return sa; 117820Sigor@sysoev.ru 117920Sigor@sysoev.ru invalid_address: 118020Sigor@sysoev.ru 118120Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid IPv6 address in \"%V\"", addr); 118220Sigor@sysoev.ru 118320Sigor@sysoev.ru return NULL; 118420Sigor@sysoev.ru 118520Sigor@sysoev.ru #else 118620Sigor@sysoev.ru 118720Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "IPv6 socket \"%V\" is not supported", addr); 118820Sigor@sysoev.ru 118920Sigor@sysoev.ru return NULL; 119020Sigor@sysoev.ru 119120Sigor@sysoev.ru #endif 119220Sigor@sysoev.ru } 119320Sigor@sysoev.ru 119420Sigor@sysoev.ru 119520Sigor@sysoev.ru static nxt_sockaddr_t * 119665Sigor@sysoev.ru nxt_runtime_sockaddr_inet_parse(nxt_task_t *task, nxt_mp_t *mp, 119726Sigor@sysoev.ru nxt_str_t *string) 119820Sigor@sysoev.ru { 119920Sigor@sysoev.ru u_char *p, *ip; 120020Sigor@sysoev.ru size_t length; 120126Sigor@sysoev.ru in_addr_t addr; 120220Sigor@sysoev.ru nxt_int_t port; 120320Sigor@sysoev.ru nxt_sockaddr_t *sa; 120420Sigor@sysoev.ru 120526Sigor@sysoev.ru addr = INADDR_ANY; 120620Sigor@sysoev.ru 120726Sigor@sysoev.ru length = string->length; 120826Sigor@sysoev.ru ip = string->start; 120920Sigor@sysoev.ru 121020Sigor@sysoev.ru p = nxt_memchr(ip, ':', length); 121120Sigor@sysoev.ru 121220Sigor@sysoev.ru if (p == NULL) { 121320Sigor@sysoev.ru 121420Sigor@sysoev.ru /* single value port, or address */ 121520Sigor@sysoev.ru 121620Sigor@sysoev.ru port = nxt_int_parse(ip, length); 121720Sigor@sysoev.ru 121820Sigor@sysoev.ru if (port > 0) { 121920Sigor@sysoev.ru /* "*:XX" */ 122020Sigor@sysoev.ru 122120Sigor@sysoev.ru if (port < 1 || port > 65535) { 122220Sigor@sysoev.ru goto invalid_port; 122320Sigor@sysoev.ru } 122420Sigor@sysoev.ru 122520Sigor@sysoev.ru } else { 122620Sigor@sysoev.ru /* "x.x.x.x" */ 122720Sigor@sysoev.ru 122826Sigor@sysoev.ru addr = nxt_inet_addr(ip, length); 122920Sigor@sysoev.ru 123026Sigor@sysoev.ru if (addr == INADDR_NONE) { 123120Sigor@sysoev.ru goto invalid_port; 123220Sigor@sysoev.ru } 123320Sigor@sysoev.ru 123420Sigor@sysoev.ru port = 8080; 123520Sigor@sysoev.ru } 123620Sigor@sysoev.ru 123720Sigor@sysoev.ru } else { 123820Sigor@sysoev.ru 123920Sigor@sysoev.ru /* x.x.x.x:XX */ 124020Sigor@sysoev.ru 124120Sigor@sysoev.ru p++; 124220Sigor@sysoev.ru length = (ip + length) - p; 124320Sigor@sysoev.ru port = nxt_int_parse(p, length); 124420Sigor@sysoev.ru 124520Sigor@sysoev.ru if (port < 1 || port > 65535) { 124620Sigor@sysoev.ru goto invalid_port; 124720Sigor@sysoev.ru } 124820Sigor@sysoev.ru 124920Sigor@sysoev.ru length = (p - 1) - ip; 125020Sigor@sysoev.ru 125120Sigor@sysoev.ru if (length != 1 || ip[0] != '*') { 125226Sigor@sysoev.ru addr = nxt_inet_addr(ip, length); 125320Sigor@sysoev.ru 125426Sigor@sysoev.ru if (addr == INADDR_NONE) { 125520Sigor@sysoev.ru goto invalid_addr; 125620Sigor@sysoev.ru } 125720Sigor@sysoev.ru 125820Sigor@sysoev.ru /* "x.x.x.x:XX" */ 125920Sigor@sysoev.ru } 126020Sigor@sysoev.ru } 126120Sigor@sysoev.ru 126220Sigor@sysoev.ru sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in), 126320Sigor@sysoev.ru NXT_INET_ADDR_STR_LEN); 126420Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) { 126520Sigor@sysoev.ru return NULL; 126620Sigor@sysoev.ru } 126720Sigor@sysoev.ru 126820Sigor@sysoev.ru sa->type = SOCK_STREAM; 126920Sigor@sysoev.ru 127020Sigor@sysoev.ru sa->u.sockaddr_in.sin_family = AF_INET; 127120Sigor@sysoev.ru sa->u.sockaddr_in.sin_port = htons((in_port_t) port); 127226Sigor@sysoev.ru sa->u.sockaddr_in.sin_addr.s_addr = addr; 127320Sigor@sysoev.ru 127420Sigor@sysoev.ru return sa; 127520Sigor@sysoev.ru 127620Sigor@sysoev.ru invalid_port: 127720Sigor@sysoev.ru 127826Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid port in \"%V\"", string); 127920Sigor@sysoev.ru 128020Sigor@sysoev.ru return NULL; 128120Sigor@sysoev.ru 128220Sigor@sysoev.ru invalid_addr: 128320Sigor@sysoev.ru 128426Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid address in \"%V\"", string); 128520Sigor@sysoev.ru 128620Sigor@sysoev.ru return NULL; 128720Sigor@sysoev.ru } 128820Sigor@sysoev.ru 128920Sigor@sysoev.ru 129020Sigor@sysoev.ru nxt_listen_socket_t * 129120Sigor@sysoev.ru nxt_runtime_listen_socket_add(nxt_runtime_t *rt, nxt_sockaddr_t *sa) 129220Sigor@sysoev.ru { 129365Sigor@sysoev.ru nxt_mp_t *mp; 129420Sigor@sysoev.ru nxt_listen_socket_t *ls; 129520Sigor@sysoev.ru 129620Sigor@sysoev.ru ls = nxt_array_zero_add(rt->listen_sockets); 129720Sigor@sysoev.ru if (ls == NULL) { 129820Sigor@sysoev.ru return NULL; 129920Sigor@sysoev.ru } 130020Sigor@sysoev.ru 130120Sigor@sysoev.ru mp = rt->mem_pool; 130220Sigor@sysoev.ru 130320Sigor@sysoev.ru ls->sockaddr = nxt_sockaddr_create(mp, &sa->u.sockaddr, sa->socklen, 130420Sigor@sysoev.ru sa->length); 130520Sigor@sysoev.ru if (ls->sockaddr == NULL) { 130620Sigor@sysoev.ru return NULL; 130720Sigor@sysoev.ru } 130820Sigor@sysoev.ru 130920Sigor@sysoev.ru ls->sockaddr->type = sa->type; 131020Sigor@sysoev.ru 131120Sigor@sysoev.ru nxt_sockaddr_text(ls->sockaddr); 131220Sigor@sysoev.ru 131320Sigor@sysoev.ru ls->socket = -1; 131420Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 131520Sigor@sysoev.ru 131620Sigor@sysoev.ru return ls; 131720Sigor@sysoev.ru } 131820Sigor@sysoev.ru 131920Sigor@sysoev.ru 132020Sigor@sysoev.ru static nxt_int_t 132120Sigor@sysoev.ru nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt) 132220Sigor@sysoev.ru { 132320Sigor@sysoev.ru size_t length; 132420Sigor@sysoev.ru char hostname[NXT_MAXHOSTNAMELEN + 1]; 132520Sigor@sysoev.ru 132620Sigor@sysoev.ru if (gethostname(hostname, NXT_MAXHOSTNAMELEN) != 0) { 132720Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "gethostname() failed %E", nxt_errno); 132820Sigor@sysoev.ru return NXT_ERROR; 132920Sigor@sysoev.ru } 133020Sigor@sysoev.ru 133120Sigor@sysoev.ru /* 133220Sigor@sysoev.ru * Linux gethostname(2): 133320Sigor@sysoev.ru * 133420Sigor@sysoev.ru * If the null-terminated hostname is too large to fit, 133520Sigor@sysoev.ru * then the name is truncated, and no error is returned. 133620Sigor@sysoev.ru * 133720Sigor@sysoev.ru * For this reason an additional byte is reserved in the buffer. 133820Sigor@sysoev.ru */ 133920Sigor@sysoev.ru hostname[NXT_MAXHOSTNAMELEN] = '\0'; 134020Sigor@sysoev.ru 134120Sigor@sysoev.ru length = nxt_strlen(hostname); 134220Sigor@sysoev.ru rt->hostname.length = length; 134320Sigor@sysoev.ru 134465Sigor@sysoev.ru rt->hostname.start = nxt_mp_nget(rt->mem_pool, length); 134520Sigor@sysoev.ru 134620Sigor@sysoev.ru if (rt->hostname.start != NULL) { 134720Sigor@sysoev.ru nxt_memcpy_lowcase(rt->hostname.start, (u_char *) hostname, length); 134820Sigor@sysoev.ru return NXT_OK; 134920Sigor@sysoev.ru } 135020Sigor@sysoev.ru 135120Sigor@sysoev.ru return NXT_ERROR; 135220Sigor@sysoev.ru } 135320Sigor@sysoev.ru 135420Sigor@sysoev.ru 135520Sigor@sysoev.ru static nxt_int_t 135620Sigor@sysoev.ru nxt_runtime_log_files_init(nxt_runtime_t *rt) 135720Sigor@sysoev.ru { 135820Sigor@sysoev.ru nxt_file_t *file; 135920Sigor@sysoev.ru nxt_list_t *log_files; 136020Sigor@sysoev.ru 136120Sigor@sysoev.ru log_files = nxt_list_create(rt->mem_pool, 1, sizeof(nxt_file_t)); 136220Sigor@sysoev.ru 136320Sigor@sysoev.ru if (nxt_fast_path(log_files != NULL)) { 136420Sigor@sysoev.ru rt->log_files = log_files; 136520Sigor@sysoev.ru 1366230Sigor@sysoev.ru /* Preallocate the main log. This allocation cannot fail. */ 136720Sigor@sysoev.ru file = nxt_list_zero_add(log_files); 136820Sigor@sysoev.ru 136920Sigor@sysoev.ru file->fd = NXT_FILE_INVALID; 137020Sigor@sysoev.ru file->log_level = NXT_LOG_CRIT; 137120Sigor@sysoev.ru 137220Sigor@sysoev.ru return NXT_OK; 137320Sigor@sysoev.ru } 137420Sigor@sysoev.ru 137520Sigor@sysoev.ru return NXT_ERROR; 137620Sigor@sysoev.ru } 137720Sigor@sysoev.ru 137820Sigor@sysoev.ru 137920Sigor@sysoev.ru nxt_file_t * 138020Sigor@sysoev.ru nxt_runtime_log_file_add(nxt_runtime_t *rt, nxt_str_t *name) 138120Sigor@sysoev.ru { 138220Sigor@sysoev.ru nxt_int_t ret; 138320Sigor@sysoev.ru nxt_file_t *file; 138420Sigor@sysoev.ru nxt_file_name_str_t file_name; 138520Sigor@sysoev.ru 1386230Sigor@sysoev.ru ret = nxt_file_name_create(rt->mem_pool, &file_name, "V%Z", name); 138720Sigor@sysoev.ru 138820Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 138920Sigor@sysoev.ru return NULL; 139020Sigor@sysoev.ru } 139120Sigor@sysoev.ru 139220Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 139320Sigor@sysoev.ru 139420Sigor@sysoev.ru /* STUB: hardecoded case sensitive/insensitive. */ 139520Sigor@sysoev.ru 139620Sigor@sysoev.ru if (file->name != NULL 139720Sigor@sysoev.ru && nxt_file_name_eq(file->name, file_name.start)) 139820Sigor@sysoev.ru { 139920Sigor@sysoev.ru return file; 140020Sigor@sysoev.ru } 140120Sigor@sysoev.ru 140220Sigor@sysoev.ru } nxt_list_loop; 140320Sigor@sysoev.ru 140420Sigor@sysoev.ru file = nxt_list_zero_add(rt->log_files); 140520Sigor@sysoev.ru 140620Sigor@sysoev.ru if (nxt_slow_path(file == NULL)) { 140720Sigor@sysoev.ru return NULL; 140820Sigor@sysoev.ru } 140920Sigor@sysoev.ru 141020Sigor@sysoev.ru file->fd = NXT_FILE_INVALID; 141120Sigor@sysoev.ru file->log_level = NXT_LOG_CRIT; 141220Sigor@sysoev.ru file->name = file_name.start; 141320Sigor@sysoev.ru 141420Sigor@sysoev.ru return file; 141520Sigor@sysoev.ru } 141620Sigor@sysoev.ru 141720Sigor@sysoev.ru 141820Sigor@sysoev.ru static nxt_int_t 141920Sigor@sysoev.ru nxt_runtime_log_files_create(nxt_task_t *task, nxt_runtime_t *rt) 142020Sigor@sysoev.ru { 142120Sigor@sysoev.ru nxt_int_t ret; 142220Sigor@sysoev.ru nxt_file_t *file; 142320Sigor@sysoev.ru 142420Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 142520Sigor@sysoev.ru 142620Sigor@sysoev.ru ret = nxt_file_open(task, file, O_WRONLY | O_APPEND, O_CREAT, 142720Sigor@sysoev.ru NXT_FILE_OWNER_ACCESS); 142820Sigor@sysoev.ru 142920Sigor@sysoev.ru if (ret != NXT_OK) { 143020Sigor@sysoev.ru return NXT_ERROR; 143120Sigor@sysoev.ru } 143220Sigor@sysoev.ru 143320Sigor@sysoev.ru } nxt_list_loop; 143420Sigor@sysoev.ru 143520Sigor@sysoev.ru file = nxt_list_first(rt->log_files); 143620Sigor@sysoev.ru 143720Sigor@sysoev.ru return nxt_file_stderr(file); 143820Sigor@sysoev.ru } 143920Sigor@sysoev.ru 144020Sigor@sysoev.ru 144120Sigor@sysoev.ru nxt_int_t 144220Sigor@sysoev.ru nxt_runtime_listen_sockets_create(nxt_task_t *task, nxt_runtime_t *rt) 144320Sigor@sysoev.ru { 144420Sigor@sysoev.ru nxt_int_t ret; 144520Sigor@sysoev.ru nxt_uint_t c, p, ncurr, nprev; 144620Sigor@sysoev.ru nxt_listen_socket_t *curr, *prev; 144720Sigor@sysoev.ru 144820Sigor@sysoev.ru curr = rt->listen_sockets->elts; 144920Sigor@sysoev.ru ncurr = rt->listen_sockets->nelts; 145020Sigor@sysoev.ru 145120Sigor@sysoev.ru if (rt->inherited_sockets != NULL) { 145220Sigor@sysoev.ru prev = rt->inherited_sockets->elts; 145320Sigor@sysoev.ru nprev = rt->inherited_sockets->nelts; 145420Sigor@sysoev.ru 145520Sigor@sysoev.ru } else { 145620Sigor@sysoev.ru prev = NULL; 145720Sigor@sysoev.ru nprev = 0; 145820Sigor@sysoev.ru } 145920Sigor@sysoev.ru 146020Sigor@sysoev.ru for (c = 0; c < ncurr; c++) { 146120Sigor@sysoev.ru 146220Sigor@sysoev.ru for (p = 0; p < nprev; p++) { 146320Sigor@sysoev.ru 146420Sigor@sysoev.ru if (nxt_sockaddr_cmp(curr[c].sockaddr, prev[p].sockaddr)) { 146520Sigor@sysoev.ru 146620Sigor@sysoev.ru ret = nxt_listen_socket_update(task, &curr[c], &prev[p]); 146720Sigor@sysoev.ru if (ret != NXT_OK) { 146820Sigor@sysoev.ru return NXT_ERROR; 146920Sigor@sysoev.ru } 147020Sigor@sysoev.ru 147120Sigor@sysoev.ru goto next; 147220Sigor@sysoev.ru } 147320Sigor@sysoev.ru } 147420Sigor@sysoev.ru 147520Sigor@sysoev.ru if (nxt_listen_socket_create(task, &curr[c], 0) != NXT_OK) { 147620Sigor@sysoev.ru return NXT_ERROR; 147720Sigor@sysoev.ru } 147820Sigor@sysoev.ru 147920Sigor@sysoev.ru next: 148020Sigor@sysoev.ru 148120Sigor@sysoev.ru continue; 148220Sigor@sysoev.ru } 148320Sigor@sysoev.ru 148420Sigor@sysoev.ru return NXT_OK; 148520Sigor@sysoev.ru } 148620Sigor@sysoev.ru 148720Sigor@sysoev.ru 148820Sigor@sysoev.ru nxt_int_t 148920Sigor@sysoev.ru nxt_runtime_listen_sockets_enable(nxt_task_t *task, nxt_runtime_t *rt) 149020Sigor@sysoev.ru { 149120Sigor@sysoev.ru nxt_uint_t i, n; 149220Sigor@sysoev.ru nxt_listen_socket_t *ls; 149320Sigor@sysoev.ru 149420Sigor@sysoev.ru ls = rt->listen_sockets->elts; 149520Sigor@sysoev.ru n = rt->listen_sockets->nelts; 149620Sigor@sysoev.ru 149720Sigor@sysoev.ru for (i = 0; i < n; i++) { 149820Sigor@sysoev.ru if (ls[i].flags == NXT_NONBLOCK) { 149954Sigor@sysoev.ru if (nxt_listen_event(task, &ls[i]) == NULL) { 150020Sigor@sysoev.ru return NXT_ERROR; 150120Sigor@sysoev.ru } 150220Sigor@sysoev.ru } 150320Sigor@sysoev.ru } 150420Sigor@sysoev.ru 150520Sigor@sysoev.ru return NXT_OK; 150620Sigor@sysoev.ru } 150720Sigor@sysoev.ru 150820Sigor@sysoev.ru 150920Sigor@sysoev.ru nxt_str_t * 151065Sigor@sysoev.ru nxt_current_directory(nxt_mp_t *mp) 151120Sigor@sysoev.ru { 151220Sigor@sysoev.ru size_t length; 151320Sigor@sysoev.ru u_char *p; 151420Sigor@sysoev.ru nxt_str_t *name; 151520Sigor@sysoev.ru char buf[NXT_MAX_PATH_LEN]; 151620Sigor@sysoev.ru 151720Sigor@sysoev.ru length = nxt_dir_current(buf, NXT_MAX_PATH_LEN); 151820Sigor@sysoev.ru 151920Sigor@sysoev.ru if (nxt_fast_path(length != 0)) { 152020Sigor@sysoev.ru name = nxt_str_alloc(mp, length + 1); 152120Sigor@sysoev.ru 152220Sigor@sysoev.ru if (nxt_fast_path(name != NULL)) { 152320Sigor@sysoev.ru p = nxt_cpymem(name->start, buf, length); 152420Sigor@sysoev.ru *p = '/'; 152520Sigor@sysoev.ru 152620Sigor@sysoev.ru return name; 152720Sigor@sysoev.ru } 152820Sigor@sysoev.ru } 152920Sigor@sysoev.ru 153020Sigor@sysoev.ru return NULL; 153120Sigor@sysoev.ru } 153220Sigor@sysoev.ru 153320Sigor@sysoev.ru 153420Sigor@sysoev.ru static nxt_int_t 153520Sigor@sysoev.ru nxt_runtime_pid_file_create(nxt_task_t *task, nxt_file_name_t *pid_file) 153620Sigor@sysoev.ru { 153720Sigor@sysoev.ru ssize_t length; 153820Sigor@sysoev.ru nxt_int_t n; 153920Sigor@sysoev.ru nxt_file_t file; 154020Sigor@sysoev.ru u_char pid[NXT_INT64_T_LEN + NXT_LINEFEED_SIZE]; 154120Sigor@sysoev.ru 154220Sigor@sysoev.ru nxt_memzero(&file, sizeof(nxt_file_t)); 154320Sigor@sysoev.ru 154420Sigor@sysoev.ru file.name = pid_file; 154520Sigor@sysoev.ru 154620Sigor@sysoev.ru n = nxt_file_open(task, &file, O_WRONLY, O_CREAT | O_TRUNC, 154720Sigor@sysoev.ru NXT_FILE_DEFAULT_ACCESS); 154820Sigor@sysoev.ru 154920Sigor@sysoev.ru if (n != NXT_OK) { 155020Sigor@sysoev.ru return NXT_ERROR; 155120Sigor@sysoev.ru } 155220Sigor@sysoev.ru 155320Sigor@sysoev.ru length = nxt_sprintf(pid, pid + sizeof(pid), "%PI%n", nxt_pid) - pid; 155420Sigor@sysoev.ru 155520Sigor@sysoev.ru if (nxt_file_write(&file, pid, length, 0) != length) { 155620Sigor@sysoev.ru return NXT_ERROR; 155720Sigor@sysoev.ru } 155820Sigor@sysoev.ru 155920Sigor@sysoev.ru nxt_file_close(task, &file); 156020Sigor@sysoev.ru 156120Sigor@sysoev.ru return NXT_OK; 156220Sigor@sysoev.ru } 156320Sigor@sysoev.ru 156420Sigor@sysoev.ru 156520Sigor@sysoev.ru nxt_process_t * 156642Smax.romanov@nginx.com nxt_runtime_process_new(nxt_runtime_t *rt) 156720Sigor@sysoev.ru { 156820Sigor@sysoev.ru nxt_process_t *process; 156920Sigor@sysoev.ru 157020Sigor@sysoev.ru /* TODO: memory failures. */ 157120Sigor@sysoev.ru 157265Sigor@sysoev.ru process = nxt_mp_zalloc(rt->mem_pool, sizeof(nxt_process_t)); 157342Smax.romanov@nginx.com if (nxt_slow_path(process == NULL)) { 157442Smax.romanov@nginx.com return NULL; 157542Smax.romanov@nginx.com } 157642Smax.romanov@nginx.com 157742Smax.romanov@nginx.com nxt_queue_init(&process->ports); 157842Smax.romanov@nginx.com 157990Smax.romanov@nginx.com nxt_thread_mutex_create(&process->incoming_mutex); 158090Smax.romanov@nginx.com nxt_thread_mutex_create(&process->outgoing_mutex); 1581141Smax.romanov@nginx.com nxt_thread_mutex_create(&process->cp_mutex); 158290Smax.romanov@nginx.com 1583349Smax.romanov@nginx.com process->use_count = 1; 1584349Smax.romanov@nginx.com 158542Smax.romanov@nginx.com return process; 158642Smax.romanov@nginx.com } 158742Smax.romanov@nginx.com 158842Smax.romanov@nginx.com 1589196Smax.romanov@nginx.com static void 1590141Smax.romanov@nginx.com nxt_runtime_process_destroy(nxt_runtime_t *rt, nxt_process_t *process) 1591141Smax.romanov@nginx.com { 1592341Smax.romanov@nginx.com nxt_port_t *port; 1593341Smax.romanov@nginx.com nxt_lvlhsh_each_t lhe; 1594341Smax.romanov@nginx.com 1595349Smax.romanov@nginx.com nxt_assert(process->use_count == 0); 1596196Smax.romanov@nginx.com nxt_assert(process->registered == 0); 1597164Smax.romanov@nginx.com 1598141Smax.romanov@nginx.com nxt_port_mmaps_destroy(process->incoming, 1); 1599141Smax.romanov@nginx.com nxt_port_mmaps_destroy(process->outgoing, 1); 1600141Smax.romanov@nginx.com 1601341Smax.romanov@nginx.com port = nxt_port_hash_first(&process->connected_ports, &lhe); 1602141Smax.romanov@nginx.com 1603341Smax.romanov@nginx.com while(port != NULL) { 1604341Smax.romanov@nginx.com nxt_port_hash_remove(&process->connected_ports, port); 1605341Smax.romanov@nginx.com 1606341Smax.romanov@nginx.com port = nxt_port_hash_first(&process->connected_ports, &lhe); 1607141Smax.romanov@nginx.com } 1608141Smax.romanov@nginx.com 1609141Smax.romanov@nginx.com nxt_thread_mutex_destroy(&process->incoming_mutex); 1610141Smax.romanov@nginx.com nxt_thread_mutex_destroy(&process->outgoing_mutex); 1611141Smax.romanov@nginx.com nxt_thread_mutex_destroy(&process->cp_mutex); 1612141Smax.romanov@nginx.com 1613141Smax.romanov@nginx.com nxt_mp_free(rt->mem_pool, process); 1614141Smax.romanov@nginx.com } 1615141Smax.romanov@nginx.com 1616141Smax.romanov@nginx.com 161742Smax.romanov@nginx.com static nxt_int_t 161842Smax.romanov@nginx.com nxt_runtime_lvlhsh_pid_test(nxt_lvlhsh_query_t *lhq, void *data) 161942Smax.romanov@nginx.com { 162042Smax.romanov@nginx.com nxt_process_t *process; 162142Smax.romanov@nginx.com 162242Smax.romanov@nginx.com process = data; 162342Smax.romanov@nginx.com 1624277Sigor@sysoev.ru if (lhq->key.length == sizeof(nxt_pid_t) 1625277Sigor@sysoev.ru && *(nxt_pid_t *) lhq->key.start == process->pid) 1626277Sigor@sysoev.ru { 162742Smax.romanov@nginx.com return NXT_OK; 162842Smax.romanov@nginx.com } 162942Smax.romanov@nginx.com 163042Smax.romanov@nginx.com return NXT_DECLINED; 163142Smax.romanov@nginx.com } 163242Smax.romanov@nginx.com 163342Smax.romanov@nginx.com static const nxt_lvlhsh_proto_t lvlhsh_processes_proto nxt_aligned(64) = { 163442Smax.romanov@nginx.com NXT_LVLHSH_DEFAULT, 163542Smax.romanov@nginx.com nxt_runtime_lvlhsh_pid_test, 163642Smax.romanov@nginx.com nxt_lvlhsh_alloc, 163742Smax.romanov@nginx.com nxt_lvlhsh_free, 163842Smax.romanov@nginx.com }; 163942Smax.romanov@nginx.com 164042Smax.romanov@nginx.com 1641196Smax.romanov@nginx.com nxt_inline void 1642196Smax.romanov@nginx.com nxt_runtime_process_lhq_pid(nxt_lvlhsh_query_t *lhq, nxt_pid_t *pid) 1643196Smax.romanov@nginx.com { 1644196Smax.romanov@nginx.com lhq->key_hash = nxt_murmur_hash2(pid, sizeof(*pid)); 1645196Smax.romanov@nginx.com lhq->key.length = sizeof(*pid); 1646196Smax.romanov@nginx.com lhq->key.start = (u_char *) pid; 1647196Smax.romanov@nginx.com lhq->proto = &lvlhsh_processes_proto; 1648196Smax.romanov@nginx.com } 1649196Smax.romanov@nginx.com 1650196Smax.romanov@nginx.com 165142Smax.romanov@nginx.com nxt_process_t * 165242Smax.romanov@nginx.com nxt_runtime_process_find(nxt_runtime_t *rt, nxt_pid_t pid) 165342Smax.romanov@nginx.com { 1654196Smax.romanov@nginx.com nxt_process_t *process; 165542Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 165642Smax.romanov@nginx.com 1657196Smax.romanov@nginx.com process = NULL; 1658196Smax.romanov@nginx.com 1659196Smax.romanov@nginx.com nxt_runtime_process_lhq_pid(&lhq, &pid); 1660196Smax.romanov@nginx.com 1661196Smax.romanov@nginx.com nxt_thread_mutex_lock(&rt->processes_mutex); 166242Smax.romanov@nginx.com 166342Smax.romanov@nginx.com if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) { 1664196Smax.romanov@nginx.com process = lhq.value; 1665196Smax.romanov@nginx.com 1666196Smax.romanov@nginx.com } else { 1667196Smax.romanov@nginx.com nxt_thread_log_debug("process %PI not found", pid); 166842Smax.romanov@nginx.com } 166942Smax.romanov@nginx.com 1670196Smax.romanov@nginx.com nxt_thread_mutex_unlock(&rt->processes_mutex); 167142Smax.romanov@nginx.com 1672196Smax.romanov@nginx.com return process; 167342Smax.romanov@nginx.com } 167442Smax.romanov@nginx.com 167542Smax.romanov@nginx.com 167642Smax.romanov@nginx.com nxt_process_t * 167742Smax.romanov@nginx.com nxt_runtime_process_get(nxt_runtime_t *rt, nxt_pid_t pid) 167842Smax.romanov@nginx.com { 167942Smax.romanov@nginx.com nxt_process_t *process; 168042Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 168142Smax.romanov@nginx.com 1682196Smax.romanov@nginx.com nxt_runtime_process_lhq_pid(&lhq, &pid); 1683196Smax.romanov@nginx.com 1684196Smax.romanov@nginx.com nxt_thread_mutex_lock(&rt->processes_mutex); 168542Smax.romanov@nginx.com 168642Smax.romanov@nginx.com if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) { 168742Smax.romanov@nginx.com nxt_thread_log_debug("process %PI found", pid); 1688196Smax.romanov@nginx.com 1689196Smax.romanov@nginx.com nxt_thread_mutex_unlock(&rt->processes_mutex); 1690349Smax.romanov@nginx.com 1691349Smax.romanov@nginx.com process = lhq.value; 1692349Smax.romanov@nginx.com process->use_count++; 1693349Smax.romanov@nginx.com 1694349Smax.romanov@nginx.com return process; 169542Smax.romanov@nginx.com } 169642Smax.romanov@nginx.com 169742Smax.romanov@nginx.com process = nxt_runtime_process_new(rt); 169820Sigor@sysoev.ru if (nxt_slow_path(process == NULL)) { 169920Sigor@sysoev.ru return NULL; 170020Sigor@sysoev.ru } 170120Sigor@sysoev.ru 170242Smax.romanov@nginx.com process->pid = pid; 170342Smax.romanov@nginx.com 170442Smax.romanov@nginx.com lhq.replace = 0; 170542Smax.romanov@nginx.com lhq.value = process; 170642Smax.romanov@nginx.com lhq.pool = rt->mem_pool; 170742Smax.romanov@nginx.com 170842Smax.romanov@nginx.com switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) { 170942Smax.romanov@nginx.com 171042Smax.romanov@nginx.com case NXT_OK: 171142Smax.romanov@nginx.com if (rt->nprocesses == 0) { 171242Smax.romanov@nginx.com rt->mprocess = process; 171342Smax.romanov@nginx.com } 171442Smax.romanov@nginx.com 171542Smax.romanov@nginx.com rt->nprocesses++; 171642Smax.romanov@nginx.com 1717196Smax.romanov@nginx.com process->registered = 1; 1718196Smax.romanov@nginx.com 171942Smax.romanov@nginx.com nxt_thread_log_debug("process %PI insert", pid); 172042Smax.romanov@nginx.com break; 172142Smax.romanov@nginx.com 172242Smax.romanov@nginx.com default: 172342Smax.romanov@nginx.com nxt_thread_log_debug("process %PI insert failed", pid); 172442Smax.romanov@nginx.com break; 172520Sigor@sysoev.ru } 172620Sigor@sysoev.ru 1727196Smax.romanov@nginx.com nxt_thread_mutex_unlock(&rt->processes_mutex); 1728196Smax.romanov@nginx.com 172920Sigor@sysoev.ru return process; 173020Sigor@sysoev.ru } 173142Smax.romanov@nginx.com 173242Smax.romanov@nginx.com 173342Smax.romanov@nginx.com void 1734343Smax.romanov@nginx.com nxt_runtime_process_add(nxt_task_t *task, nxt_process_t *process) 173542Smax.romanov@nginx.com { 173642Smax.romanov@nginx.com nxt_port_t *port; 1737343Smax.romanov@nginx.com nxt_runtime_t *rt; 173842Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 173942Smax.romanov@nginx.com 1740196Smax.romanov@nginx.com nxt_assert(process->registered == 0); 1741196Smax.romanov@nginx.com 1742343Smax.romanov@nginx.com rt = task->thread->runtime; 1743343Smax.romanov@nginx.com 1744196Smax.romanov@nginx.com nxt_runtime_process_lhq_pid(&lhq, &process->pid); 1745196Smax.romanov@nginx.com 174642Smax.romanov@nginx.com lhq.replace = 0; 174742Smax.romanov@nginx.com lhq.value = process; 174842Smax.romanov@nginx.com lhq.pool = rt->mem_pool; 174942Smax.romanov@nginx.com 1750196Smax.romanov@nginx.com nxt_thread_mutex_lock(&rt->processes_mutex); 1751196Smax.romanov@nginx.com 175242Smax.romanov@nginx.com switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) { 175342Smax.romanov@nginx.com 175442Smax.romanov@nginx.com case NXT_OK: 175542Smax.romanov@nginx.com if (rt->nprocesses == 0) { 175642Smax.romanov@nginx.com rt->mprocess = process; 175742Smax.romanov@nginx.com } 175842Smax.romanov@nginx.com 175942Smax.romanov@nginx.com rt->nprocesses++; 176042Smax.romanov@nginx.com 176142Smax.romanov@nginx.com nxt_process_port_each(process, port) { 176242Smax.romanov@nginx.com 1763141Smax.romanov@nginx.com port->pid = process->pid; 1764141Smax.romanov@nginx.com 1765343Smax.romanov@nginx.com nxt_runtime_port_add(task, port); 176642Smax.romanov@nginx.com 176742Smax.romanov@nginx.com } nxt_process_port_loop; 176842Smax.romanov@nginx.com 1769196Smax.romanov@nginx.com process->registered = 1; 1770196Smax.romanov@nginx.com 1771196Smax.romanov@nginx.com nxt_thread_log_debug("process %PI added", process->pid); 177242Smax.romanov@nginx.com break; 177342Smax.romanov@nginx.com 177442Smax.romanov@nginx.com default: 1775196Smax.romanov@nginx.com nxt_thread_log_debug("process %PI failed to add", process->pid); 177642Smax.romanov@nginx.com break; 177742Smax.romanov@nginx.com } 1778196Smax.romanov@nginx.com 1779196Smax.romanov@nginx.com nxt_thread_mutex_unlock(&rt->processes_mutex); 1780196Smax.romanov@nginx.com } 1781196Smax.romanov@nginx.com 1782196Smax.romanov@nginx.com 1783196Smax.romanov@nginx.com static nxt_process_t * 1784196Smax.romanov@nginx.com nxt_runtime_process_remove_pid(nxt_runtime_t *rt, nxt_pid_t pid) 1785196Smax.romanov@nginx.com { 1786196Smax.romanov@nginx.com nxt_process_t *process; 1787196Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 1788196Smax.romanov@nginx.com 1789196Smax.romanov@nginx.com process = NULL; 1790196Smax.romanov@nginx.com 1791196Smax.romanov@nginx.com nxt_runtime_process_lhq_pid(&lhq, &pid); 1792196Smax.romanov@nginx.com 1793196Smax.romanov@nginx.com lhq.pool = rt->mem_pool; 1794196Smax.romanov@nginx.com 1795196Smax.romanov@nginx.com nxt_thread_mutex_lock(&rt->processes_mutex); 1796196Smax.romanov@nginx.com 1797196Smax.romanov@nginx.com switch (nxt_lvlhsh_delete(&rt->processes, &lhq)) { 1798196Smax.romanov@nginx.com 1799196Smax.romanov@nginx.com case NXT_OK: 1800196Smax.romanov@nginx.com rt->nprocesses--; 1801196Smax.romanov@nginx.com 1802196Smax.romanov@nginx.com process = lhq.value; 1803196Smax.romanov@nginx.com 1804196Smax.romanov@nginx.com process->registered = 0; 1805196Smax.romanov@nginx.com 1806196Smax.romanov@nginx.com nxt_thread_log_debug("process %PI removed", pid); 1807196Smax.romanov@nginx.com break; 1808196Smax.romanov@nginx.com 1809196Smax.romanov@nginx.com default: 1810196Smax.romanov@nginx.com nxt_thread_log_debug("process %PI remove failed", pid); 1811196Smax.romanov@nginx.com break; 1812196Smax.romanov@nginx.com } 1813196Smax.romanov@nginx.com 1814196Smax.romanov@nginx.com nxt_thread_mutex_unlock(&rt->processes_mutex); 1815196Smax.romanov@nginx.com 1816196Smax.romanov@nginx.com return process; 181742Smax.romanov@nginx.com } 181842Smax.romanov@nginx.com 181942Smax.romanov@nginx.com 182042Smax.romanov@nginx.com void 1821349Smax.romanov@nginx.com nxt_process_use(nxt_task_t *task, nxt_process_t *process, int i) 182242Smax.romanov@nginx.com { 1823343Smax.romanov@nginx.com nxt_runtime_t *rt; 1824343Smax.romanov@nginx.com 1825349Smax.romanov@nginx.com process->use_count += i; 1826349Smax.romanov@nginx.com 1827349Smax.romanov@nginx.com if (process->use_count == 0) { 1828349Smax.romanov@nginx.com rt = task->thread->runtime; 1829349Smax.romanov@nginx.com 1830196Smax.romanov@nginx.com if (process->registered == 1) { 1831196Smax.romanov@nginx.com nxt_runtime_process_remove_pid(rt, process->pid); 1832164Smax.romanov@nginx.com } 1833164Smax.romanov@nginx.com 1834196Smax.romanov@nginx.com nxt_runtime_process_destroy(rt, process); 183542Smax.romanov@nginx.com } 183642Smax.romanov@nginx.com } 183742Smax.romanov@nginx.com 183842Smax.romanov@nginx.com 183942Smax.romanov@nginx.com nxt_process_t * 184042Smax.romanov@nginx.com nxt_runtime_process_first(nxt_runtime_t *rt, nxt_lvlhsh_each_t *lhe) 184142Smax.romanov@nginx.com { 184242Smax.romanov@nginx.com nxt_memzero(lhe, sizeof(nxt_lvlhsh_each_t)); 184342Smax.romanov@nginx.com 184442Smax.romanov@nginx.com lhe->proto = &lvlhsh_processes_proto; 184542Smax.romanov@nginx.com 184642Smax.romanov@nginx.com return nxt_runtime_process_next(rt, lhe); 184742Smax.romanov@nginx.com } 184842Smax.romanov@nginx.com 184942Smax.romanov@nginx.com 185074Smax.romanov@nginx.com nxt_port_t * 185174Smax.romanov@nginx.com nxt_runtime_port_first(nxt_runtime_t *rt, nxt_lvlhsh_each_t *lhe) 185274Smax.romanov@nginx.com { 185375Smax.romanov@nginx.com return nxt_port_hash_first(&rt->ports, lhe); 185474Smax.romanov@nginx.com } 185574Smax.romanov@nginx.com 185674Smax.romanov@nginx.com 185742Smax.romanov@nginx.com void 1858343Smax.romanov@nginx.com nxt_runtime_port_add(nxt_task_t *task, nxt_port_t *port) 185942Smax.romanov@nginx.com { 1860348Smax.romanov@nginx.com nxt_int_t res; 1861343Smax.romanov@nginx.com nxt_runtime_t *rt; 1862343Smax.romanov@nginx.com 1863343Smax.romanov@nginx.com rt = task->thread->runtime; 1864343Smax.romanov@nginx.com 1865348Smax.romanov@nginx.com res = nxt_port_hash_add(&rt->ports, port); 1866348Smax.romanov@nginx.com 1867348Smax.romanov@nginx.com if (res != NXT_OK) { 1868348Smax.romanov@nginx.com return; 1869348Smax.romanov@nginx.com } 1870141Smax.romanov@nginx.com 1871141Smax.romanov@nginx.com rt->port_by_type[port->type] = port; 1872343Smax.romanov@nginx.com 1873343Smax.romanov@nginx.com nxt_port_use(task, port, 1); 187442Smax.romanov@nginx.com } 187542Smax.romanov@nginx.com 187642Smax.romanov@nginx.com 187742Smax.romanov@nginx.com void 1878343Smax.romanov@nginx.com nxt_runtime_port_remove(nxt_task_t *task, nxt_port_t *port) 187942Smax.romanov@nginx.com { 1880348Smax.romanov@nginx.com nxt_int_t res; 1881343Smax.romanov@nginx.com nxt_runtime_t *rt; 1882343Smax.romanov@nginx.com 1883343Smax.romanov@nginx.com rt = task->thread->runtime; 1884343Smax.romanov@nginx.com 1885348Smax.romanov@nginx.com res = nxt_port_hash_remove(&rt->ports, port); 1886348Smax.romanov@nginx.com 1887348Smax.romanov@nginx.com if (res != NXT_OK) { 1888348Smax.romanov@nginx.com return; 1889348Smax.romanov@nginx.com } 1890125Smax.romanov@nginx.com 1891141Smax.romanov@nginx.com if (rt->port_by_type[port->type] == port) { 1892141Smax.romanov@nginx.com rt->port_by_type[port->type] = NULL; 1893141Smax.romanov@nginx.com } 1894343Smax.romanov@nginx.com 1895343Smax.romanov@nginx.com nxt_port_use(task, port, -1); 189642Smax.romanov@nginx.com } 189742Smax.romanov@nginx.com 189842Smax.romanov@nginx.com 189942Smax.romanov@nginx.com nxt_port_t * 190042Smax.romanov@nginx.com nxt_runtime_port_find(nxt_runtime_t *rt, nxt_pid_t pid, 190142Smax.romanov@nginx.com nxt_port_id_t port_id) 190242Smax.romanov@nginx.com { 190375Smax.romanov@nginx.com return nxt_port_hash_find(&rt->ports, pid, port_id); 190442Smax.romanov@nginx.com } 1905