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> 1120Sigor@sysoev.ru #include <nxt_master_process.h> 1220Sigor@sysoev.ru 1320Sigor@sysoev.ru 1420Sigor@sysoev.ru static nxt_int_t nxt_runtime_inherited_listen_sockets(nxt_task_t *task, 1520Sigor@sysoev.ru nxt_runtime_t *rt); 1620Sigor@sysoev.ru static nxt_int_t nxt_runtime_systemd_listen_sockets(nxt_task_t *task, 1720Sigor@sysoev.ru nxt_runtime_t *rt); 1820Sigor@sysoev.ru static nxt_int_t nxt_runtime_event_engines(nxt_task_t *task, nxt_runtime_t *rt); 1920Sigor@sysoev.ru static nxt_int_t nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt); 2020Sigor@sysoev.ru static void nxt_runtime_start(nxt_task_t *task, void *obj, void *data); 2120Sigor@sysoev.ru static void nxt_runtime_initial_start(nxt_task_t *task); 2220Sigor@sysoev.ru static void nxt_single_process_start(nxt_thread_t *thr, nxt_task_t *task, 2320Sigor@sysoev.ru nxt_runtime_t *rt); 2420Sigor@sysoev.ru static void nxt_runtime_close_idle_connections(nxt_event_engine_t *engine); 2520Sigor@sysoev.ru static void nxt_runtime_exit(nxt_task_t *task, void *obj, void *data); 2620Sigor@sysoev.ru static nxt_int_t nxt_runtime_event_engine_change(nxt_task_t *task, 2720Sigor@sysoev.ru nxt_runtime_t *rt); 2820Sigor@sysoev.ru static nxt_int_t nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt); 2920Sigor@sysoev.ru static nxt_int_t nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt); 3020Sigor@sysoev.ru static nxt_sockaddr_t *nxt_runtime_sockaddr_parse(nxt_task_t *task, 3120Sigor@sysoev.ru nxt_mem_pool_t *mp, nxt_str_t *addr); 3220Sigor@sysoev.ru static nxt_sockaddr_t *nxt_runtime_sockaddr_unix_parse(nxt_task_t *task, 3320Sigor@sysoev.ru nxt_mem_pool_t *mp, nxt_str_t *addr); 3420Sigor@sysoev.ru static nxt_sockaddr_t *nxt_runtime_sockaddr_inet6_parse(nxt_task_t *task, 3520Sigor@sysoev.ru nxt_mem_pool_t *mp, nxt_str_t *addr); 3620Sigor@sysoev.ru static nxt_sockaddr_t *nxt_runtime_sockaddr_inet_parse(nxt_task_t *task, 3720Sigor@sysoev.ru nxt_mem_pool_t *mp, nxt_str_t *addr); 3820Sigor@sysoev.ru static nxt_int_t nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt); 3920Sigor@sysoev.ru static nxt_int_t nxt_runtime_log_files_init(nxt_runtime_t *rt); 4020Sigor@sysoev.ru static nxt_int_t nxt_runtime_log_files_create(nxt_task_t *task, 4120Sigor@sysoev.ru nxt_runtime_t *rt); 4220Sigor@sysoev.ru static nxt_int_t nxt_runtime_pid_file_create(nxt_task_t *task, 4320Sigor@sysoev.ru nxt_file_name_t *pid_file); 4420Sigor@sysoev.ru 4520Sigor@sysoev.ru #if (NXT_THREADS) 4620Sigor@sysoev.ru static void nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt, 4720Sigor@sysoev.ru nxt_runtime_cont_t cont); 4820Sigor@sysoev.ru #endif 4920Sigor@sysoev.ru 5020Sigor@sysoev.ru 5120Sigor@sysoev.ru nxt_int_t 5220Sigor@sysoev.ru nxt_runtime_create(nxt_task_t *task) 5320Sigor@sysoev.ru { 5420Sigor@sysoev.ru nxt_int_t ret; 5520Sigor@sysoev.ru nxt_array_t *listen_sockets; 5620Sigor@sysoev.ru nxt_runtime_t *rt; 5720Sigor@sysoev.ru nxt_mem_pool_t *mp; 5820Sigor@sysoev.ru 5920Sigor@sysoev.ru mp = nxt_mem_pool_create(1024); 6020Sigor@sysoev.ru 6120Sigor@sysoev.ru if (nxt_slow_path(mp == NULL)) { 6220Sigor@sysoev.ru return NXT_ERROR; 6320Sigor@sysoev.ru } 6420Sigor@sysoev.ru 6520Sigor@sysoev.ru /* This alloction cannot fail. */ 6620Sigor@sysoev.ru rt = nxt_mem_zalloc(mp, sizeof(nxt_runtime_t)); 6720Sigor@sysoev.ru 6820Sigor@sysoev.ru task->thread->runtime = rt; 6920Sigor@sysoev.ru rt->mem_pool = mp; 7020Sigor@sysoev.ru 7120Sigor@sysoev.ru rt->prefix = nxt_current_directory(mp); 7220Sigor@sysoev.ru if (nxt_slow_path(rt->prefix == NULL)) { 7320Sigor@sysoev.ru goto fail; 7420Sigor@sysoev.ru } 7520Sigor@sysoev.ru 7620Sigor@sysoev.ru rt->conf_prefix = rt->prefix; 7720Sigor@sysoev.ru 7820Sigor@sysoev.ru rt->services = nxt_services_init(mp); 7920Sigor@sysoev.ru if (nxt_slow_path(rt->services == NULL)) { 8020Sigor@sysoev.ru goto fail; 8120Sigor@sysoev.ru } 8220Sigor@sysoev.ru 8320Sigor@sysoev.ru listen_sockets = nxt_array_create(mp, 1, sizeof(nxt_listen_socket_t)); 8420Sigor@sysoev.ru if (nxt_slow_path(listen_sockets == NULL)) { 8520Sigor@sysoev.ru goto fail; 8620Sigor@sysoev.ru } 8720Sigor@sysoev.ru 8820Sigor@sysoev.ru rt->listen_sockets = listen_sockets; 8920Sigor@sysoev.ru 9020Sigor@sysoev.ru ret = nxt_runtime_inherited_listen_sockets(task, rt); 9120Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 9220Sigor@sysoev.ru goto fail; 9320Sigor@sysoev.ru } 9420Sigor@sysoev.ru 9520Sigor@sysoev.ru if (nxt_runtime_hostname(task, rt) != NXT_OK) { 9620Sigor@sysoev.ru goto fail; 9720Sigor@sysoev.ru } 9820Sigor@sysoev.ru 9920Sigor@sysoev.ru if (nxt_slow_path(nxt_runtime_log_files_init(rt) != NXT_OK)) { 10020Sigor@sysoev.ru goto fail; 10120Sigor@sysoev.ru } 10220Sigor@sysoev.ru 10320Sigor@sysoev.ru if (nxt_runtime_event_engines(task, rt) != NXT_OK) { 10420Sigor@sysoev.ru goto fail; 10520Sigor@sysoev.ru } 10620Sigor@sysoev.ru 10720Sigor@sysoev.ru if (nxt_slow_path(nxt_runtime_thread_pools(task->thread, rt) != NXT_OK)) { 10820Sigor@sysoev.ru goto fail; 10920Sigor@sysoev.ru } 11020Sigor@sysoev.ru 11120Sigor@sysoev.ru rt->start = nxt_runtime_initial_start; 11220Sigor@sysoev.ru 11320Sigor@sysoev.ru nxt_work_queue_add(&task->thread->engine->fast_work_queue, 11420Sigor@sysoev.ru nxt_runtime_start, task, rt, NULL); 11520Sigor@sysoev.ru 11620Sigor@sysoev.ru return NXT_OK; 11720Sigor@sysoev.ru 11820Sigor@sysoev.ru fail: 11920Sigor@sysoev.ru 12020Sigor@sysoev.ru nxt_mem_pool_destroy(mp); 12120Sigor@sysoev.ru 12220Sigor@sysoev.ru return NXT_ERROR; 12320Sigor@sysoev.ru } 12420Sigor@sysoev.ru 12520Sigor@sysoev.ru 12620Sigor@sysoev.ru static nxt_int_t 12720Sigor@sysoev.ru nxt_runtime_inherited_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt) 12820Sigor@sysoev.ru { 12920Sigor@sysoev.ru u_char *v, *p; 13020Sigor@sysoev.ru nxt_int_t type; 13120Sigor@sysoev.ru nxt_array_t *inherited_sockets; 13220Sigor@sysoev.ru nxt_socket_t s; 13320Sigor@sysoev.ru nxt_listen_socket_t *ls; 13420Sigor@sysoev.ru 13520Sigor@sysoev.ru v = (u_char *) getenv("NGINX"); 13620Sigor@sysoev.ru 13720Sigor@sysoev.ru if (v == NULL) { 13820Sigor@sysoev.ru return nxt_runtime_systemd_listen_sockets(task, rt); 13920Sigor@sysoev.ru } 14020Sigor@sysoev.ru 14120Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "using inherited listen sockets: %s", v); 14220Sigor@sysoev.ru 14320Sigor@sysoev.ru inherited_sockets = nxt_array_create(rt->mem_pool, 14420Sigor@sysoev.ru 1, sizeof(nxt_listen_socket_t)); 14520Sigor@sysoev.ru if (inherited_sockets == NULL) { 14620Sigor@sysoev.ru return NXT_ERROR; 14720Sigor@sysoev.ru } 14820Sigor@sysoev.ru 14920Sigor@sysoev.ru rt->inherited_sockets = inherited_sockets; 15020Sigor@sysoev.ru 15120Sigor@sysoev.ru for (p = v; *p != '\0'; p++) { 15220Sigor@sysoev.ru 15320Sigor@sysoev.ru if (*p == ';') { 15420Sigor@sysoev.ru s = nxt_int_parse(v, p - v); 15520Sigor@sysoev.ru 15620Sigor@sysoev.ru if (nxt_slow_path(s < 0)) { 15720Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid socket number " 15820Sigor@sysoev.ru "\"%s\" in NGINX environment variable, " 15920Sigor@sysoev.ru "ignoring the rest of the variable", v); 16020Sigor@sysoev.ru return NXT_ERROR; 16120Sigor@sysoev.ru } 16220Sigor@sysoev.ru 16320Sigor@sysoev.ru v = p + 1; 16420Sigor@sysoev.ru 16520Sigor@sysoev.ru ls = nxt_array_zero_add(inherited_sockets); 16620Sigor@sysoev.ru if (nxt_slow_path(ls == NULL)) { 16720Sigor@sysoev.ru return NXT_ERROR; 16820Sigor@sysoev.ru } 16920Sigor@sysoev.ru 17020Sigor@sysoev.ru ls->socket = s; 17120Sigor@sysoev.ru 17220Sigor@sysoev.ru ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s); 17320Sigor@sysoev.ru if (nxt_slow_path(ls->sockaddr == NULL)) { 17420Sigor@sysoev.ru return NXT_ERROR; 17520Sigor@sysoev.ru } 17620Sigor@sysoev.ru 17720Sigor@sysoev.ru type = nxt_socket_getsockopt(task, s, SOL_SOCKET, SO_TYPE); 17820Sigor@sysoev.ru if (nxt_slow_path(type == -1)) { 17920Sigor@sysoev.ru return NXT_ERROR; 18020Sigor@sysoev.ru } 18120Sigor@sysoev.ru 18220Sigor@sysoev.ru ls->sockaddr->type = (uint16_t) type; 18320Sigor@sysoev.ru } 18420Sigor@sysoev.ru } 18520Sigor@sysoev.ru 18620Sigor@sysoev.ru return NXT_OK; 18720Sigor@sysoev.ru } 18820Sigor@sysoev.ru 18920Sigor@sysoev.ru 19020Sigor@sysoev.ru static nxt_int_t 19120Sigor@sysoev.ru nxt_runtime_systemd_listen_sockets(nxt_task_t *task, nxt_runtime_t *rt) 19220Sigor@sysoev.ru { 19320Sigor@sysoev.ru u_char *nfd, *pid; 19420Sigor@sysoev.ru nxt_int_t n; 19520Sigor@sysoev.ru nxt_array_t *inherited_sockets; 19620Sigor@sysoev.ru nxt_socket_t s; 19720Sigor@sysoev.ru nxt_listen_socket_t *ls; 19820Sigor@sysoev.ru 19920Sigor@sysoev.ru /* 20020Sigor@sysoev.ru * Number of listening sockets passed. The socket 20120Sigor@sysoev.ru * descriptors start from number 3 and are sequential. 20220Sigor@sysoev.ru */ 20320Sigor@sysoev.ru nfd = (u_char *) getenv("LISTEN_FDS"); 20420Sigor@sysoev.ru if (nfd == NULL) { 20520Sigor@sysoev.ru return NXT_OK; 20620Sigor@sysoev.ru } 20720Sigor@sysoev.ru 20820Sigor@sysoev.ru /* The pid of the service process. */ 20920Sigor@sysoev.ru pid = (u_char *) getenv("LISTEN_PID"); 21020Sigor@sysoev.ru if (pid == NULL) { 21120Sigor@sysoev.ru return NXT_OK; 21220Sigor@sysoev.ru } 21320Sigor@sysoev.ru 21420Sigor@sysoev.ru n = nxt_int_parse(nfd, nxt_strlen(nfd)); 21520Sigor@sysoev.ru if (n < 0) { 21620Sigor@sysoev.ru return NXT_OK; 21720Sigor@sysoev.ru } 21820Sigor@sysoev.ru 21920Sigor@sysoev.ru if (nxt_pid != nxt_int_parse(pid, nxt_strlen(pid))) { 22020Sigor@sysoev.ru return NXT_OK; 22120Sigor@sysoev.ru } 22220Sigor@sysoev.ru 22320Sigor@sysoev.ru nxt_log(task, NXT_LOG_INFO, "using %s systemd listen sockets", n); 22420Sigor@sysoev.ru 22520Sigor@sysoev.ru inherited_sockets = nxt_array_create(rt->mem_pool, 22620Sigor@sysoev.ru n, sizeof(nxt_listen_socket_t)); 22720Sigor@sysoev.ru if (inherited_sockets == NULL) { 22820Sigor@sysoev.ru return NXT_ERROR; 22920Sigor@sysoev.ru } 23020Sigor@sysoev.ru 23120Sigor@sysoev.ru rt->inherited_sockets = inherited_sockets; 23220Sigor@sysoev.ru 23320Sigor@sysoev.ru for (s = 3; s < n; s++) { 23420Sigor@sysoev.ru ls = nxt_array_zero_add(inherited_sockets); 23520Sigor@sysoev.ru if (nxt_slow_path(ls == NULL)) { 23620Sigor@sysoev.ru return NXT_ERROR; 23720Sigor@sysoev.ru } 23820Sigor@sysoev.ru 23920Sigor@sysoev.ru ls->socket = s; 24020Sigor@sysoev.ru 24120Sigor@sysoev.ru ls->sockaddr = nxt_getsockname(task, rt->mem_pool, s); 24220Sigor@sysoev.ru if (nxt_slow_path(ls->sockaddr == NULL)) { 24320Sigor@sysoev.ru return NXT_ERROR; 24420Sigor@sysoev.ru } 24520Sigor@sysoev.ru 24620Sigor@sysoev.ru ls->sockaddr->type = SOCK_STREAM; 24720Sigor@sysoev.ru } 24820Sigor@sysoev.ru 24920Sigor@sysoev.ru return NXT_OK; 25020Sigor@sysoev.ru } 25120Sigor@sysoev.ru 25220Sigor@sysoev.ru 25320Sigor@sysoev.ru static nxt_int_t 25420Sigor@sysoev.ru nxt_runtime_event_engines(nxt_task_t *task, nxt_runtime_t *rt) 25520Sigor@sysoev.ru { 256*53Sigor@sysoev.ru nxt_thread_t *thread; 257*53Sigor@sysoev.ru nxt_event_engine_t *engine; 25820Sigor@sysoev.ru const nxt_event_interface_t *interface; 25920Sigor@sysoev.ru 26020Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", NULL); 26120Sigor@sysoev.ru 26220Sigor@sysoev.ru if (nxt_slow_path(interface == NULL)) { 26320Sigor@sysoev.ru /* TODO: log */ 26420Sigor@sysoev.ru return NXT_ERROR; 26520Sigor@sysoev.ru } 26620Sigor@sysoev.ru 26720Sigor@sysoev.ru engine = nxt_event_engine_create(task, interface, 26820Sigor@sysoev.ru nxt_master_process_signals, 0, 0); 26920Sigor@sysoev.ru 27020Sigor@sysoev.ru if (nxt_slow_path(engine == NULL)) { 27120Sigor@sysoev.ru return NXT_ERROR; 27220Sigor@sysoev.ru } 27320Sigor@sysoev.ru 274*53Sigor@sysoev.ru thread = task->thread; 275*53Sigor@sysoev.ru thread->engine = engine; 276*53Sigor@sysoev.ru thread->fiber = &engine->fibers->fiber; 277*53Sigor@sysoev.ru 27820Sigor@sysoev.ru engine->id = rt->last_engine_id++; 279*53Sigor@sysoev.ru 280*53Sigor@sysoev.ru nxt_queue_init(&rt->engines); 281*53Sigor@sysoev.ru nxt_queue_insert_tail(&rt->engines, &engine->link); 28220Sigor@sysoev.ru 28320Sigor@sysoev.ru return NXT_OK; 28420Sigor@sysoev.ru } 28520Sigor@sysoev.ru 28620Sigor@sysoev.ru 28720Sigor@sysoev.ru static nxt_int_t 28820Sigor@sysoev.ru nxt_runtime_thread_pools(nxt_thread_t *thr, nxt_runtime_t *rt) 28920Sigor@sysoev.ru { 29020Sigor@sysoev.ru #if (NXT_THREADS) 29120Sigor@sysoev.ru nxt_int_t ret; 29220Sigor@sysoev.ru nxt_array_t *thread_pools; 29320Sigor@sysoev.ru 29420Sigor@sysoev.ru thread_pools = nxt_array_create(rt->mem_pool, 1, 29520Sigor@sysoev.ru sizeof(nxt_thread_pool_t *)); 29620Sigor@sysoev.ru 29720Sigor@sysoev.ru if (nxt_slow_path(thread_pools == NULL)) { 29820Sigor@sysoev.ru return NXT_ERROR; 29920Sigor@sysoev.ru } 30020Sigor@sysoev.ru 30120Sigor@sysoev.ru rt->thread_pools = thread_pools; 30220Sigor@sysoev.ru ret = nxt_runtime_thread_pool_create(thr, rt, 2, 60000 * 1000000LL); 30320Sigor@sysoev.ru 30420Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 30520Sigor@sysoev.ru return NXT_ERROR; 30620Sigor@sysoev.ru } 30720Sigor@sysoev.ru 30820Sigor@sysoev.ru #endif 30920Sigor@sysoev.ru 31020Sigor@sysoev.ru return NXT_OK; 31120Sigor@sysoev.ru } 31220Sigor@sysoev.ru 31320Sigor@sysoev.ru 31420Sigor@sysoev.ru static void 31520Sigor@sysoev.ru nxt_runtime_start(nxt_task_t *task, void *obj, void *data) 31620Sigor@sysoev.ru { 31720Sigor@sysoev.ru nxt_uint_t i; 31820Sigor@sysoev.ru nxt_runtime_t *rt; 31920Sigor@sysoev.ru 32020Sigor@sysoev.ru rt = obj; 32120Sigor@sysoev.ru 32220Sigor@sysoev.ru nxt_debug(task, "rt conf done"); 32320Sigor@sysoev.ru 32420Sigor@sysoev.ru nxt_mem_pool_debug_lock(rt->mem_pool, nxt_thread_tid(task->thread)); 32520Sigor@sysoev.ru 32620Sigor@sysoev.ru task->thread->log->ctx_handler = NULL; 32720Sigor@sysoev.ru task->thread->log->ctx = NULL; 32820Sigor@sysoev.ru 32920Sigor@sysoev.ru if (nxt_runtime_conf_init(task, rt) != NXT_OK) { 33020Sigor@sysoev.ru goto fail; 33120Sigor@sysoev.ru } 33220Sigor@sysoev.ru 33320Sigor@sysoev.ru for (i = 0; i < nxt_init_modules_n; i++) { 33420Sigor@sysoev.ru if (nxt_init_modules[i](task->thread, rt) != NXT_OK) { 33520Sigor@sysoev.ru goto fail; 33620Sigor@sysoev.ru } 33720Sigor@sysoev.ru } 33820Sigor@sysoev.ru 33920Sigor@sysoev.ru if (nxt_runtime_log_files_create(task, rt) != NXT_OK) { 34020Sigor@sysoev.ru goto fail; 34120Sigor@sysoev.ru } 34220Sigor@sysoev.ru 34320Sigor@sysoev.ru if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) { 34420Sigor@sysoev.ru goto fail; 34520Sigor@sysoev.ru } 34620Sigor@sysoev.ru 34720Sigor@sysoev.ru #if (NXT_THREADS) 34820Sigor@sysoev.ru 34920Sigor@sysoev.ru /* 35020Sigor@sysoev.ru * Thread pools should be destroyed before starting worker 35120Sigor@sysoev.ru * processes, because thread pool semaphores will stick in 35220Sigor@sysoev.ru * locked state in new processes after fork(). 35320Sigor@sysoev.ru */ 35420Sigor@sysoev.ru nxt_runtime_thread_pool_destroy(task, rt, rt->start); 35520Sigor@sysoev.ru 35620Sigor@sysoev.ru #else 35720Sigor@sysoev.ru 35820Sigor@sysoev.ru rt->start(task->thread, rt); 35920Sigor@sysoev.ru 36020Sigor@sysoev.ru #endif 36120Sigor@sysoev.ru 36220Sigor@sysoev.ru return; 36320Sigor@sysoev.ru 36420Sigor@sysoev.ru fail: 36520Sigor@sysoev.ru 36620Sigor@sysoev.ru nxt_runtime_quit(task); 36720Sigor@sysoev.ru } 36820Sigor@sysoev.ru 36920Sigor@sysoev.ru 37020Sigor@sysoev.ru static void 37120Sigor@sysoev.ru nxt_runtime_initial_start(nxt_task_t *task) 37220Sigor@sysoev.ru { 37320Sigor@sysoev.ru nxt_int_t ret; 37420Sigor@sysoev.ru nxt_thread_t *thr; 37520Sigor@sysoev.ru nxt_runtime_t *rt; 37620Sigor@sysoev.ru const nxt_event_interface_t *interface; 37720Sigor@sysoev.ru 37820Sigor@sysoev.ru thr = task->thread; 37920Sigor@sysoev.ru rt = thr->runtime; 38020Sigor@sysoev.ru 38120Sigor@sysoev.ru if (rt->inherited_sockets == NULL && rt->daemon) { 38220Sigor@sysoev.ru 38320Sigor@sysoev.ru if (nxt_process_daemon(task) != NXT_OK) { 38420Sigor@sysoev.ru goto fail; 38520Sigor@sysoev.ru } 38620Sigor@sysoev.ru 38720Sigor@sysoev.ru /* 38820Sigor@sysoev.ru * An event engine should be updated after fork() 38920Sigor@sysoev.ru * even if an event facility was not changed because: 39020Sigor@sysoev.ru * 1) inherited kqueue descriptor is invalid, 39120Sigor@sysoev.ru * 2) the signal thread is not inherited. 39220Sigor@sysoev.ru */ 39320Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", rt->engine); 39420Sigor@sysoev.ru if (interface == NULL) { 39520Sigor@sysoev.ru goto fail; 39620Sigor@sysoev.ru } 39720Sigor@sysoev.ru 39820Sigor@sysoev.ru ret = nxt_event_engine_change(task->thread->engine, interface, 39920Sigor@sysoev.ru rt->batch); 40020Sigor@sysoev.ru if (ret != NXT_OK) { 40120Sigor@sysoev.ru goto fail; 40220Sigor@sysoev.ru } 40320Sigor@sysoev.ru } 40420Sigor@sysoev.ru 40520Sigor@sysoev.ru ret = nxt_runtime_pid_file_create(task, rt->pid_file); 40620Sigor@sysoev.ru if (ret != NXT_OK) { 40720Sigor@sysoev.ru goto fail; 40820Sigor@sysoev.ru } 40920Sigor@sysoev.ru 41020Sigor@sysoev.ru if (nxt_runtime_event_engine_change(task, rt) != NXT_OK) { 41120Sigor@sysoev.ru goto fail; 41220Sigor@sysoev.ru } 41320Sigor@sysoev.ru 41420Sigor@sysoev.ru thr->engine->max_connections = rt->engine_connections; 41520Sigor@sysoev.ru 41620Sigor@sysoev.ru if (rt->master_process) { 41720Sigor@sysoev.ru if (nxt_master_process_start(thr, task, rt) != NXT_ERROR) { 41820Sigor@sysoev.ru return; 41920Sigor@sysoev.ru } 42020Sigor@sysoev.ru 42120Sigor@sysoev.ru } else { 42220Sigor@sysoev.ru nxt_single_process_start(thr, task, rt); 42320Sigor@sysoev.ru return; 42420Sigor@sysoev.ru } 42520Sigor@sysoev.ru 42620Sigor@sysoev.ru fail: 42720Sigor@sysoev.ru 42820Sigor@sysoev.ru nxt_runtime_quit(task); 42920Sigor@sysoev.ru } 43020Sigor@sysoev.ru 43120Sigor@sysoev.ru 43220Sigor@sysoev.ru static void 43320Sigor@sysoev.ru nxt_single_process_start(nxt_thread_t *thr, nxt_task_t *task, nxt_runtime_t *rt) 43420Sigor@sysoev.ru { 43520Sigor@sysoev.ru #if (NXT_THREADS) 43620Sigor@sysoev.ru nxt_int_t ret; 43720Sigor@sysoev.ru 43820Sigor@sysoev.ru ret = nxt_runtime_thread_pool_create(thr, rt, rt->auxiliary_threads, 43920Sigor@sysoev.ru 60000 * 1000000LL); 44020Sigor@sysoev.ru 44120Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 44220Sigor@sysoev.ru nxt_runtime_quit(task); 44320Sigor@sysoev.ru return; 44420Sigor@sysoev.ru } 44520Sigor@sysoev.ru 44620Sigor@sysoev.ru #endif 44720Sigor@sysoev.ru 44820Sigor@sysoev.ru rt->type = NXT_PROCESS_SINGLE; 44920Sigor@sysoev.ru 45020Sigor@sysoev.ru nxt_runtime_listen_sockets_enable(task, rt); 45120Sigor@sysoev.ru 45220Sigor@sysoev.ru return; 45320Sigor@sysoev.ru } 45420Sigor@sysoev.ru 45520Sigor@sysoev.ru 45620Sigor@sysoev.ru void 45720Sigor@sysoev.ru nxt_runtime_quit(nxt_task_t *task) 45820Sigor@sysoev.ru { 45920Sigor@sysoev.ru nxt_bool_t done; 46020Sigor@sysoev.ru nxt_runtime_t *rt; 46120Sigor@sysoev.ru nxt_event_engine_t *engine; 46220Sigor@sysoev.ru 46320Sigor@sysoev.ru rt = task->thread->runtime; 46420Sigor@sysoev.ru engine = task->thread->engine; 46520Sigor@sysoev.ru 46620Sigor@sysoev.ru nxt_debug(task, "exiting"); 46720Sigor@sysoev.ru 46820Sigor@sysoev.ru done = 1; 46920Sigor@sysoev.ru 47020Sigor@sysoev.ru if (!engine->shutdown) { 47120Sigor@sysoev.ru engine->shutdown = 1; 47220Sigor@sysoev.ru 47320Sigor@sysoev.ru #if (NXT_THREADS) 47420Sigor@sysoev.ru 47520Sigor@sysoev.ru if (!nxt_array_is_empty(rt->thread_pools)) { 47620Sigor@sysoev.ru nxt_runtime_thread_pool_destroy(task, rt, nxt_runtime_quit); 47720Sigor@sysoev.ru done = 0; 47820Sigor@sysoev.ru } 47920Sigor@sysoev.ru 48020Sigor@sysoev.ru #endif 48120Sigor@sysoev.ru 48220Sigor@sysoev.ru if (rt->type == NXT_PROCESS_MASTER) { 48320Sigor@sysoev.ru nxt_master_stop_worker_processes(task, rt); 48420Sigor@sysoev.ru done = 0; 48520Sigor@sysoev.ru } 48620Sigor@sysoev.ru } 48720Sigor@sysoev.ru 48820Sigor@sysoev.ru nxt_runtime_close_idle_connections(engine); 48920Sigor@sysoev.ru 49020Sigor@sysoev.ru if (done) { 49120Sigor@sysoev.ru nxt_work_queue_add(&engine->fast_work_queue, nxt_runtime_exit, 49220Sigor@sysoev.ru task, rt, engine); 49320Sigor@sysoev.ru } 49420Sigor@sysoev.ru } 49520Sigor@sysoev.ru 49620Sigor@sysoev.ru 49720Sigor@sysoev.ru static void 49820Sigor@sysoev.ru nxt_runtime_close_idle_connections(nxt_event_engine_t *engine) 49920Sigor@sysoev.ru { 50020Sigor@sysoev.ru nxt_queue_t *idle; 50120Sigor@sysoev.ru nxt_queue_link_t *link, *next; 50220Sigor@sysoev.ru nxt_event_conn_t *c; 50320Sigor@sysoev.ru 50420Sigor@sysoev.ru nxt_debug(&engine->task, "close idle connections"); 50520Sigor@sysoev.ru 50620Sigor@sysoev.ru idle = &engine->idle_connections; 50720Sigor@sysoev.ru 50820Sigor@sysoev.ru for (link = nxt_queue_head(idle); 50920Sigor@sysoev.ru link != nxt_queue_tail(idle); 51020Sigor@sysoev.ru link = next) 51120Sigor@sysoev.ru { 51220Sigor@sysoev.ru next = nxt_queue_next(link); 51320Sigor@sysoev.ru c = nxt_queue_link_data(link, nxt_event_conn_t, link); 51420Sigor@sysoev.ru 51520Sigor@sysoev.ru if (!c->socket.read_ready) { 51620Sigor@sysoev.ru nxt_queue_remove(link); 51720Sigor@sysoev.ru nxt_event_conn_close(engine, c); 51820Sigor@sysoev.ru } 51920Sigor@sysoev.ru } 52020Sigor@sysoev.ru } 52120Sigor@sysoev.ru 52220Sigor@sysoev.ru 52320Sigor@sysoev.ru static void 52420Sigor@sysoev.ru nxt_runtime_exit(nxt_task_t *task, void *obj, void *data) 52520Sigor@sysoev.ru { 52620Sigor@sysoev.ru nxt_runtime_t *rt; 52720Sigor@sysoev.ru nxt_event_engine_t *engine; 52820Sigor@sysoev.ru 52920Sigor@sysoev.ru rt = obj; 53020Sigor@sysoev.ru engine = data; 53120Sigor@sysoev.ru 53220Sigor@sysoev.ru #if (NXT_THREADS) 53320Sigor@sysoev.ru 53420Sigor@sysoev.ru nxt_debug(task, "thread pools: %d", rt->thread_pools->nelts); 53520Sigor@sysoev.ru 53620Sigor@sysoev.ru if (!nxt_array_is_empty(rt->thread_pools)) { 53720Sigor@sysoev.ru return; 53820Sigor@sysoev.ru } 53920Sigor@sysoev.ru 54020Sigor@sysoev.ru #endif 54120Sigor@sysoev.ru 54220Sigor@sysoev.ru if (rt->type <= NXT_PROCESS_MASTER) { 54320Sigor@sysoev.ru if (rt->pid_file != NULL) { 54420Sigor@sysoev.ru nxt_file_delete(rt->pid_file); 54520Sigor@sysoev.ru } 54620Sigor@sysoev.ru } 54720Sigor@sysoev.ru 54820Sigor@sysoev.ru if (!engine->event.signal_support) { 54920Sigor@sysoev.ru nxt_event_engine_signals_stop(engine); 55020Sigor@sysoev.ru } 55120Sigor@sysoev.ru 55220Sigor@sysoev.ru nxt_debug(task, "exit"); 55320Sigor@sysoev.ru 55420Sigor@sysoev.ru exit(0); 55520Sigor@sysoev.ru nxt_unreachable(); 55620Sigor@sysoev.ru } 55720Sigor@sysoev.ru 55820Sigor@sysoev.ru 55920Sigor@sysoev.ru static nxt_int_t 56020Sigor@sysoev.ru nxt_runtime_event_engine_change(nxt_task_t *task, nxt_runtime_t *rt) 56120Sigor@sysoev.ru { 56220Sigor@sysoev.ru nxt_event_engine_t *engine; 56320Sigor@sysoev.ru const nxt_event_interface_t *interface; 56420Sigor@sysoev.ru 56520Sigor@sysoev.ru engine = task->thread->engine; 56620Sigor@sysoev.ru 56720Sigor@sysoev.ru if (engine->batch == rt->batch 56820Sigor@sysoev.ru && nxt_strcmp(engine->event.name, rt->engine) == 0) 56920Sigor@sysoev.ru { 57020Sigor@sysoev.ru return NXT_OK; 57120Sigor@sysoev.ru } 57220Sigor@sysoev.ru 57320Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", rt->engine); 57420Sigor@sysoev.ru 57520Sigor@sysoev.ru if (interface != NULL) { 57620Sigor@sysoev.ru return nxt_event_engine_change(engine, interface, rt->batch); 57720Sigor@sysoev.ru } 57820Sigor@sysoev.ru 57920Sigor@sysoev.ru return NXT_ERROR; 58020Sigor@sysoev.ru } 58120Sigor@sysoev.ru 58220Sigor@sysoev.ru 58320Sigor@sysoev.ru void 58420Sigor@sysoev.ru nxt_runtime_event_engine_free(nxt_runtime_t *rt) 58520Sigor@sysoev.ru { 586*53Sigor@sysoev.ru nxt_queue_link_t *link; 587*53Sigor@sysoev.ru nxt_event_engine_t *engine; 58820Sigor@sysoev.ru 589*53Sigor@sysoev.ru link = nxt_queue_first(&rt->engines); 590*53Sigor@sysoev.ru nxt_queue_remove(link); 59120Sigor@sysoev.ru 592*53Sigor@sysoev.ru engine = nxt_queue_link_data(link, nxt_event_engine_t, link); 59320Sigor@sysoev.ru nxt_event_engine_free(engine); 59420Sigor@sysoev.ru } 59520Sigor@sysoev.ru 59620Sigor@sysoev.ru 59720Sigor@sysoev.ru #if (NXT_THREADS) 59820Sigor@sysoev.ru 59920Sigor@sysoev.ru static void nxt_runtime_thread_pool_init(void); 60020Sigor@sysoev.ru static void nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj, 60120Sigor@sysoev.ru void *data); 60220Sigor@sysoev.ru 60320Sigor@sysoev.ru 60420Sigor@sysoev.ru nxt_int_t 60520Sigor@sysoev.ru nxt_runtime_thread_pool_create(nxt_thread_t *thr, nxt_runtime_t *rt, 60620Sigor@sysoev.ru nxt_uint_t max_threads, nxt_nsec_t timeout) 60720Sigor@sysoev.ru { 60820Sigor@sysoev.ru nxt_thread_pool_t *thread_pool, **tp; 60920Sigor@sysoev.ru 61020Sigor@sysoev.ru tp = nxt_array_add(rt->thread_pools); 61120Sigor@sysoev.ru if (tp == NULL) { 61220Sigor@sysoev.ru return NXT_ERROR; 61320Sigor@sysoev.ru } 61420Sigor@sysoev.ru 61520Sigor@sysoev.ru thread_pool = nxt_thread_pool_create(max_threads, timeout, 61620Sigor@sysoev.ru nxt_runtime_thread_pool_init, 61720Sigor@sysoev.ru thr->engine, 61820Sigor@sysoev.ru nxt_runtime_thread_pool_exit); 61920Sigor@sysoev.ru 62020Sigor@sysoev.ru if (nxt_fast_path(thread_pool != NULL)) { 62120Sigor@sysoev.ru *tp = thread_pool; 62220Sigor@sysoev.ru } 62320Sigor@sysoev.ru 62420Sigor@sysoev.ru return NXT_OK; 62520Sigor@sysoev.ru } 62620Sigor@sysoev.ru 62720Sigor@sysoev.ru 62820Sigor@sysoev.ru static void 62920Sigor@sysoev.ru nxt_runtime_thread_pool_destroy(nxt_task_t *task, nxt_runtime_t *rt, 63020Sigor@sysoev.ru nxt_runtime_cont_t cont) 63120Sigor@sysoev.ru { 63220Sigor@sysoev.ru nxt_uint_t n; 63320Sigor@sysoev.ru nxt_thread_pool_t **tp; 63420Sigor@sysoev.ru 63520Sigor@sysoev.ru rt->continuation = cont; 63620Sigor@sysoev.ru 63720Sigor@sysoev.ru n = rt->thread_pools->nelts; 63820Sigor@sysoev.ru 63920Sigor@sysoev.ru if (n == 0) { 64020Sigor@sysoev.ru cont(task); 64120Sigor@sysoev.ru return; 64220Sigor@sysoev.ru } 64320Sigor@sysoev.ru 64420Sigor@sysoev.ru tp = rt->thread_pools->elts; 64520Sigor@sysoev.ru 64620Sigor@sysoev.ru do { 64720Sigor@sysoev.ru nxt_thread_pool_destroy(*tp); 64820Sigor@sysoev.ru 64920Sigor@sysoev.ru tp++; 65020Sigor@sysoev.ru n--; 65120Sigor@sysoev.ru } while (n != 0); 65220Sigor@sysoev.ru } 65320Sigor@sysoev.ru 65420Sigor@sysoev.ru 65520Sigor@sysoev.ru static void 65620Sigor@sysoev.ru nxt_runtime_thread_pool_init(void) 65720Sigor@sysoev.ru { 65820Sigor@sysoev.ru #if (NXT_REGEX) 65920Sigor@sysoev.ru nxt_regex_init(0); 66020Sigor@sysoev.ru #endif 66120Sigor@sysoev.ru } 66220Sigor@sysoev.ru 66320Sigor@sysoev.ru 66420Sigor@sysoev.ru static void 66520Sigor@sysoev.ru nxt_runtime_thread_pool_exit(nxt_task_t *task, void *obj, void *data) 66620Sigor@sysoev.ru { 66720Sigor@sysoev.ru nxt_uint_t i, n; 66820Sigor@sysoev.ru nxt_runtime_t *rt; 66920Sigor@sysoev.ru nxt_thread_pool_t *tp, **thread_pools; 67020Sigor@sysoev.ru nxt_thread_handle_t handle; 67120Sigor@sysoev.ru 67220Sigor@sysoev.ru tp = obj; 67320Sigor@sysoev.ru 67420Sigor@sysoev.ru if (data != NULL) { 67520Sigor@sysoev.ru handle = (nxt_thread_handle_t) (uintptr_t) data; 67620Sigor@sysoev.ru nxt_thread_wait(handle); 67720Sigor@sysoev.ru } 67820Sigor@sysoev.ru 67920Sigor@sysoev.ru rt = task->thread->runtime; 68020Sigor@sysoev.ru 68120Sigor@sysoev.ru thread_pools = rt->thread_pools->elts; 68220Sigor@sysoev.ru n = rt->thread_pools->nelts; 68320Sigor@sysoev.ru 68420Sigor@sysoev.ru nxt_debug(task, "thread pools: %ui", n); 68520Sigor@sysoev.ru 68620Sigor@sysoev.ru for (i = 0; i < n; i++) { 68720Sigor@sysoev.ru 68820Sigor@sysoev.ru if (tp == thread_pools[i]) { 68920Sigor@sysoev.ru nxt_array_remove(rt->thread_pools, &thread_pools[i]); 69020Sigor@sysoev.ru 69120Sigor@sysoev.ru if (n == 1) { 69220Sigor@sysoev.ru /* The last thread pool. */ 69320Sigor@sysoev.ru rt->continuation(task); 69420Sigor@sysoev.ru } 69520Sigor@sysoev.ru 69620Sigor@sysoev.ru return; 69720Sigor@sysoev.ru } 69820Sigor@sysoev.ru } 69920Sigor@sysoev.ru } 70020Sigor@sysoev.ru 70120Sigor@sysoev.ru #endif 70220Sigor@sysoev.ru 70320Sigor@sysoev.ru 70420Sigor@sysoev.ru static nxt_int_t 70520Sigor@sysoev.ru nxt_runtime_conf_init(nxt_task_t *task, nxt_runtime_t *rt) 70620Sigor@sysoev.ru { 70720Sigor@sysoev.ru nxt_int_t ret; 70820Sigor@sysoev.ru nxt_str_t *prefix; 70920Sigor@sysoev.ru nxt_file_t *file; 71020Sigor@sysoev.ru nxt_file_name_str_t file_name; 71120Sigor@sysoev.ru const nxt_event_interface_t *interface; 71220Sigor@sysoev.ru 71320Sigor@sysoev.ru rt->daemon = 1; 71420Sigor@sysoev.ru rt->master_process = 1; 71520Sigor@sysoev.ru rt->engine_connections = 256; 71620Sigor@sysoev.ru rt->worker_processes = 1; 71720Sigor@sysoev.ru rt->auxiliary_threads = 2; 71820Sigor@sysoev.ru rt->user_cred.user = "nobody"; 71920Sigor@sysoev.ru rt->group = NULL; 72020Sigor@sysoev.ru rt->pid = "nginext.pid"; 72120Sigor@sysoev.ru rt->error_log = "error.log"; 72220Sigor@sysoev.ru 72320Sigor@sysoev.ru if (nxt_runtime_conf_read_cmd(task, rt) != NXT_OK) { 72420Sigor@sysoev.ru return NXT_ERROR; 72520Sigor@sysoev.ru } 72620Sigor@sysoev.ru 72720Sigor@sysoev.ru if (nxt_runtime_controller_socket(task, rt) != NXT_OK) { 72820Sigor@sysoev.ru return NXT_ERROR; 72920Sigor@sysoev.ru } 73020Sigor@sysoev.ru 73120Sigor@sysoev.ru if (nxt_user_cred_get(task, &rt->user_cred, rt->group) != NXT_OK) { 73220Sigor@sysoev.ru return NXT_ERROR; 73320Sigor@sysoev.ru } 73420Sigor@sysoev.ru 73520Sigor@sysoev.ru /* An engine's parameters. */ 73620Sigor@sysoev.ru 73720Sigor@sysoev.ru interface = nxt_service_get(rt->services, "engine", rt->engine); 73820Sigor@sysoev.ru if (interface == NULL) { 73920Sigor@sysoev.ru return NXT_ERROR; 74020Sigor@sysoev.ru } 74120Sigor@sysoev.ru 74220Sigor@sysoev.ru rt->engine = interface->name; 74320Sigor@sysoev.ru 74420Sigor@sysoev.ru prefix = nxt_file_name_is_absolute(rt->pid) ? NULL : rt->prefix; 74520Sigor@sysoev.ru 74620Sigor@sysoev.ru ret = nxt_file_name_create(rt->mem_pool, &file_name, "%V%s%Z", 74720Sigor@sysoev.ru prefix, rt->pid); 74820Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 74920Sigor@sysoev.ru return NXT_ERROR; 75020Sigor@sysoev.ru } 75120Sigor@sysoev.ru 75220Sigor@sysoev.ru rt->pid_file = file_name.start; 75320Sigor@sysoev.ru 75420Sigor@sysoev.ru prefix = nxt_file_name_is_absolute(rt->error_log) ? NULL : rt->prefix; 75520Sigor@sysoev.ru 75620Sigor@sysoev.ru ret = nxt_file_name_create(rt->mem_pool, &file_name, "%V%s%Z", 75720Sigor@sysoev.ru prefix, rt->error_log); 75820Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 75920Sigor@sysoev.ru return NXT_ERROR; 76020Sigor@sysoev.ru } 76120Sigor@sysoev.ru 76220Sigor@sysoev.ru file = nxt_list_first(rt->log_files); 76320Sigor@sysoev.ru file->name = file_name.start; 76420Sigor@sysoev.ru 76520Sigor@sysoev.ru return NXT_OK; 76620Sigor@sysoev.ru } 76720Sigor@sysoev.ru 76820Sigor@sysoev.ru 76920Sigor@sysoev.ru static nxt_int_t 77020Sigor@sysoev.ru nxt_runtime_conf_read_cmd(nxt_task_t *task, nxt_runtime_t *rt) 77120Sigor@sysoev.ru { 77220Sigor@sysoev.ru char *p, **argv; 77320Sigor@sysoev.ru nxt_int_t n; 77420Sigor@sysoev.ru nxt_str_t addr; 77520Sigor@sysoev.ru nxt_sockaddr_t *sa; 77620Sigor@sysoev.ru 77720Sigor@sysoev.ru argv = nxt_process_argv; 77820Sigor@sysoev.ru 77920Sigor@sysoev.ru while (*argv != NULL) { 78020Sigor@sysoev.ru p = *argv++; 78120Sigor@sysoev.ru 78220Sigor@sysoev.ru if (nxt_strcmp(p, "--listen") == 0) { 78320Sigor@sysoev.ru if (*argv == NULL) { 78420Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 78520Sigor@sysoev.ru "no argument for option \"--listen\""); 78620Sigor@sysoev.ru return NXT_ERROR; 78720Sigor@sysoev.ru } 78820Sigor@sysoev.ru 78920Sigor@sysoev.ru p = *argv++; 79020Sigor@sysoev.ru 79120Sigor@sysoev.ru addr.length = nxt_strlen(p); 79220Sigor@sysoev.ru addr.start = (u_char *) p; 79320Sigor@sysoev.ru 79420Sigor@sysoev.ru sa = nxt_runtime_sockaddr_parse(task, rt->mem_pool, &addr); 79520Sigor@sysoev.ru 79620Sigor@sysoev.ru if (sa == NULL) { 79720Sigor@sysoev.ru return NXT_ERROR; 79820Sigor@sysoev.ru } 79920Sigor@sysoev.ru 80020Sigor@sysoev.ru rt->controller_listen = sa; 80120Sigor@sysoev.ru 80220Sigor@sysoev.ru continue; 80320Sigor@sysoev.ru } 80420Sigor@sysoev.ru 80520Sigor@sysoev.ru if (nxt_strcmp(p, "--upstream") == 0) { 80620Sigor@sysoev.ru if (*argv == NULL) { 80720Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 80820Sigor@sysoev.ru "no argument for option \"--upstream\""); 80920Sigor@sysoev.ru return NXT_ERROR; 81020Sigor@sysoev.ru } 81120Sigor@sysoev.ru 81220Sigor@sysoev.ru p = *argv++; 81320Sigor@sysoev.ru 81420Sigor@sysoev.ru rt->upstream.length = nxt_strlen(p); 81520Sigor@sysoev.ru rt->upstream.start = (u_char *) p; 81620Sigor@sysoev.ru 81720Sigor@sysoev.ru continue; 81820Sigor@sysoev.ru } 81920Sigor@sysoev.ru 82020Sigor@sysoev.ru if (nxt_strcmp(p, "--workers") == 0) { 82120Sigor@sysoev.ru if (*argv == NULL) { 82220Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 82320Sigor@sysoev.ru "no argument for option \"--workers\""); 82420Sigor@sysoev.ru return NXT_ERROR; 82520Sigor@sysoev.ru } 82620Sigor@sysoev.ru 82720Sigor@sysoev.ru p = *argv++; 82820Sigor@sysoev.ru n = nxt_int_parse((u_char *) p, nxt_strlen(p)); 82920Sigor@sysoev.ru 83020Sigor@sysoev.ru if (n < 1) { 83120Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 83220Sigor@sysoev.ru "invalid number of workers: \"%s\"", p); 83320Sigor@sysoev.ru return NXT_ERROR; 83420Sigor@sysoev.ru } 83520Sigor@sysoev.ru 83620Sigor@sysoev.ru rt->worker_processes = n; 83720Sigor@sysoev.ru 83820Sigor@sysoev.ru continue; 83920Sigor@sysoev.ru } 84020Sigor@sysoev.ru 84120Sigor@sysoev.ru if (nxt_strcmp(p, "--user") == 0) { 84220Sigor@sysoev.ru if (*argv == NULL) { 84320Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 84420Sigor@sysoev.ru "no argument for option \"--user\""); 84520Sigor@sysoev.ru return NXT_ERROR; 84620Sigor@sysoev.ru } 84720Sigor@sysoev.ru 84820Sigor@sysoev.ru p = *argv++; 84920Sigor@sysoev.ru 85020Sigor@sysoev.ru rt->user_cred.user = p; 85120Sigor@sysoev.ru 85220Sigor@sysoev.ru continue; 85320Sigor@sysoev.ru } 85420Sigor@sysoev.ru 85520Sigor@sysoev.ru if (nxt_strcmp(p, "--group") == 0) { 85620Sigor@sysoev.ru if (*argv == NULL) { 85720Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 85820Sigor@sysoev.ru "no argument for option \"--group\""); 85920Sigor@sysoev.ru return NXT_ERROR; 86020Sigor@sysoev.ru } 86120Sigor@sysoev.ru 86220Sigor@sysoev.ru p = *argv++; 86320Sigor@sysoev.ru 86420Sigor@sysoev.ru rt->group = p; 86520Sigor@sysoev.ru 86620Sigor@sysoev.ru continue; 86720Sigor@sysoev.ru } 86820Sigor@sysoev.ru 86920Sigor@sysoev.ru if (nxt_strcmp(p, "--pid") == 0) { 87020Sigor@sysoev.ru if (*argv == NULL) { 87120Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 87220Sigor@sysoev.ru "no argument for option \"--pid\""); 87320Sigor@sysoev.ru return NXT_ERROR; 87420Sigor@sysoev.ru } 87520Sigor@sysoev.ru 87620Sigor@sysoev.ru p = *argv++; 87720Sigor@sysoev.ru 87820Sigor@sysoev.ru rt->pid = p; 87920Sigor@sysoev.ru 88020Sigor@sysoev.ru continue; 88120Sigor@sysoev.ru } 88220Sigor@sysoev.ru 88320Sigor@sysoev.ru if (nxt_strcmp(p, "--log") == 0) { 88420Sigor@sysoev.ru if (*argv == NULL) { 88520Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 88620Sigor@sysoev.ru "no argument for option \"--log\""); 88720Sigor@sysoev.ru return NXT_ERROR; 88820Sigor@sysoev.ru } 88920Sigor@sysoev.ru 89020Sigor@sysoev.ru p = *argv++; 89120Sigor@sysoev.ru 89220Sigor@sysoev.ru rt->error_log = p; 89320Sigor@sysoev.ru 89420Sigor@sysoev.ru continue; 89520Sigor@sysoev.ru } 89620Sigor@sysoev.ru 89720Sigor@sysoev.ru if (nxt_strcmp(p, "--no-daemonize") == 0) { 89820Sigor@sysoev.ru rt->daemon = 0; 89920Sigor@sysoev.ru continue; 90020Sigor@sysoev.ru } 90120Sigor@sysoev.ru } 90220Sigor@sysoev.ru 90320Sigor@sysoev.ru return NXT_OK; 90420Sigor@sysoev.ru } 90520Sigor@sysoev.ru 90620Sigor@sysoev.ru 90720Sigor@sysoev.ru static nxt_sockaddr_t * 90820Sigor@sysoev.ru nxt_runtime_sockaddr_parse(nxt_task_t *task, nxt_mem_pool_t *mp, 90920Sigor@sysoev.ru nxt_str_t *addr) 91020Sigor@sysoev.ru { 91120Sigor@sysoev.ru u_char *p; 91220Sigor@sysoev.ru size_t length; 91320Sigor@sysoev.ru 91420Sigor@sysoev.ru length = addr->length; 91520Sigor@sysoev.ru p = addr->start; 91620Sigor@sysoev.ru 91720Sigor@sysoev.ru if (length >= 5 && nxt_memcmp(p, (u_char *) "unix:", 5) == 0) { 91820Sigor@sysoev.ru return nxt_runtime_sockaddr_unix_parse(task, mp, addr); 91920Sigor@sysoev.ru } 92020Sigor@sysoev.ru 92120Sigor@sysoev.ru if (length != 0 && *p == '[') { 92220Sigor@sysoev.ru return nxt_runtime_sockaddr_inet6_parse(task, mp, addr); 92320Sigor@sysoev.ru } 92420Sigor@sysoev.ru 92520Sigor@sysoev.ru return nxt_runtime_sockaddr_inet_parse(task, mp, addr); 92620Sigor@sysoev.ru } 92720Sigor@sysoev.ru 92820Sigor@sysoev.ru 92920Sigor@sysoev.ru static nxt_sockaddr_t * 93020Sigor@sysoev.ru nxt_runtime_sockaddr_unix_parse(nxt_task_t *task, nxt_mem_pool_t *mp, 93120Sigor@sysoev.ru nxt_str_t *addr) 93220Sigor@sysoev.ru { 93320Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 93420Sigor@sysoev.ru u_char *p; 93520Sigor@sysoev.ru size_t length, socklen; 93620Sigor@sysoev.ru nxt_sockaddr_t *sa; 93720Sigor@sysoev.ru 93820Sigor@sysoev.ru /* 93920Sigor@sysoev.ru * Actual sockaddr_un length can be lesser or even larger than defined 94020Sigor@sysoev.ru * struct sockaddr_un length (see comment in unix/nxt_socket.h). So 94120Sigor@sysoev.ru * limit maximum Unix domain socket address length by defined sun_path[] 94220Sigor@sysoev.ru * length because some OSes accept addresses twice larger than defined 94320Sigor@sysoev.ru * struct sockaddr_un. Also reserve space for a trailing zero to avoid 94420Sigor@sysoev.ru * ambiguity, since many OSes accept Unix domain socket addresses 94520Sigor@sysoev.ru * without a trailing zero. 94620Sigor@sysoev.ru */ 94720Sigor@sysoev.ru const size_t max_len = sizeof(struct sockaddr_un) 94820Sigor@sysoev.ru - offsetof(struct sockaddr_un, sun_path) - 1; 94920Sigor@sysoev.ru 95020Sigor@sysoev.ru /* cutting "unix:" */ 95120Sigor@sysoev.ru length = addr->length - 5; 95220Sigor@sysoev.ru p = addr->start + 5; 95320Sigor@sysoev.ru 95420Sigor@sysoev.ru if (length == 0) { 95520Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 95620Sigor@sysoev.ru "unix domain socket \"%V\" name is invalid", addr); 95720Sigor@sysoev.ru return NULL; 95820Sigor@sysoev.ru } 95920Sigor@sysoev.ru 96020Sigor@sysoev.ru if (length > max_len) { 96120Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, 96220Sigor@sysoev.ru "unix domain socket \"%V\" name is too long", addr); 96320Sigor@sysoev.ru return NULL; 96420Sigor@sysoev.ru } 96520Sigor@sysoev.ru 96620Sigor@sysoev.ru socklen = offsetof(struct sockaddr_un, sun_path) + length + 1; 96720Sigor@sysoev.ru 96820Sigor@sysoev.ru #if (NXT_LINUX) 96920Sigor@sysoev.ru 97020Sigor@sysoev.ru /* 97120Sigor@sysoev.ru * Linux unix(7): 97220Sigor@sysoev.ru * 97320Sigor@sysoev.ru * abstract: an abstract socket address is distinguished by the fact 97420Sigor@sysoev.ru * that sun_path[0] is a null byte ('\0'). The socket's address in 97520Sigor@sysoev.ru * this namespace is given by the additional bytes in sun_path that 97620Sigor@sysoev.ru * are covered by the specified length of the address structure. 97720Sigor@sysoev.ru * (Null bytes in the name have no special significance.) 97820Sigor@sysoev.ru */ 97920Sigor@sysoev.ru if (p[0] == '@') { 98020Sigor@sysoev.ru p[0] = '\0'; 98120Sigor@sysoev.ru socklen--; 98220Sigor@sysoev.ru } 98320Sigor@sysoev.ru 98420Sigor@sysoev.ru #endif 98520Sigor@sysoev.ru 98620Sigor@sysoev.ru sa = nxt_sockaddr_alloc(mp, socklen, addr->length); 98720Sigor@sysoev.ru 98820Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) { 98920Sigor@sysoev.ru return NULL; 99020Sigor@sysoev.ru } 99120Sigor@sysoev.ru 99220Sigor@sysoev.ru sa->type = SOCK_STREAM; 99320Sigor@sysoev.ru 99420Sigor@sysoev.ru sa->u.sockaddr_un.sun_family = AF_UNIX; 99520Sigor@sysoev.ru nxt_memcpy(sa->u.sockaddr_un.sun_path, p, length); 99620Sigor@sysoev.ru 99720Sigor@sysoev.ru return sa; 99820Sigor@sysoev.ru 99920Sigor@sysoev.ru #else /* !(NXT_HAVE_UNIX_DOMAIN) */ 100020Sigor@sysoev.ru 100120Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "unix domain socket \"%V\" is not supported", 100220Sigor@sysoev.ru addr); 100320Sigor@sysoev.ru 100420Sigor@sysoev.ru return NULL; 100520Sigor@sysoev.ru 100620Sigor@sysoev.ru #endif 100720Sigor@sysoev.ru } 100820Sigor@sysoev.ru 100920Sigor@sysoev.ru 101020Sigor@sysoev.ru static nxt_sockaddr_t * 101120Sigor@sysoev.ru nxt_runtime_sockaddr_inet6_parse(nxt_task_t *task, nxt_mem_pool_t *mp, 101220Sigor@sysoev.ru nxt_str_t *addr) 101320Sigor@sysoev.ru { 101420Sigor@sysoev.ru #if (NXT_INET6) 101520Sigor@sysoev.ru u_char *p, *addr, *addr_end; 101620Sigor@sysoev.ru size_t length; 101720Sigor@sysoev.ru nxt_int_t port; 101820Sigor@sysoev.ru nxt_mem_pool_t *mp; 101920Sigor@sysoev.ru nxt_sockaddr_t *sa; 102020Sigor@sysoev.ru struct in6_addr *in6_addr; 102120Sigor@sysoev.ru 102220Sigor@sysoev.ru length = addr->length - 1; 102320Sigor@sysoev.ru p = addr->start + 1; 102420Sigor@sysoev.ru 102520Sigor@sysoev.ru addr_end = nxt_memchr(p, ']', length); 102620Sigor@sysoev.ru 102720Sigor@sysoev.ru if (addr_end == NULL) { 102820Sigor@sysoev.ru goto invalid_address; 102920Sigor@sysoev.ru } 103020Sigor@sysoev.ru 103120Sigor@sysoev.ru sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in6)); 103220Sigor@sysoev.ru 103320Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) { 103420Sigor@sysoev.ru return NULL; 103520Sigor@sysoev.ru } 103620Sigor@sysoev.ru 103720Sigor@sysoev.ru in6_addr = &sa->u.sockaddr_in6.sin6_addr; 103820Sigor@sysoev.ru 103920Sigor@sysoev.ru if (nxt_inet6_addr(in6_addr, p, addr_end - p) != NXT_OK) { 104020Sigor@sysoev.ru goto invalid_address; 104120Sigor@sysoev.ru } 104220Sigor@sysoev.ru 104320Sigor@sysoev.ru p = addr_end + 1; 104420Sigor@sysoev.ru length = (p + length) - p; 104520Sigor@sysoev.ru 104620Sigor@sysoev.ru if (length == 0) { 104720Sigor@sysoev.ru goto found; 104820Sigor@sysoev.ru } 104920Sigor@sysoev.ru 105020Sigor@sysoev.ru if (*p == ':') { 105120Sigor@sysoev.ru port = nxt_int_parse(p + 1, length - 1); 105220Sigor@sysoev.ru 105320Sigor@sysoev.ru if (port >= 1 && port <= 65535) { 105420Sigor@sysoev.ru goto found; 105520Sigor@sysoev.ru } 105620Sigor@sysoev.ru } 105720Sigor@sysoev.ru 105820Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid port in \"%V\"", addr); 105920Sigor@sysoev.ru 106020Sigor@sysoev.ru return NULL; 106120Sigor@sysoev.ru 106220Sigor@sysoev.ru found: 106320Sigor@sysoev.ru 106420Sigor@sysoev.ru sa->type = SOCK_STREAM; 106520Sigor@sysoev.ru 106620Sigor@sysoev.ru sa->u.sockaddr_in6.sin6_family = AF_INET6; 106720Sigor@sysoev.ru sa->u.sockaddr_in6.sin6_port = htons((in_port_t) port); 106820Sigor@sysoev.ru 106920Sigor@sysoev.ru return sa; 107020Sigor@sysoev.ru 107120Sigor@sysoev.ru invalid_address: 107220Sigor@sysoev.ru 107320Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid IPv6 address in \"%V\"", addr); 107420Sigor@sysoev.ru 107520Sigor@sysoev.ru return NULL; 107620Sigor@sysoev.ru 107720Sigor@sysoev.ru #else 107820Sigor@sysoev.ru 107920Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "IPv6 socket \"%V\" is not supported", addr); 108020Sigor@sysoev.ru 108120Sigor@sysoev.ru return NULL; 108220Sigor@sysoev.ru 108320Sigor@sysoev.ru #endif 108420Sigor@sysoev.ru } 108520Sigor@sysoev.ru 108620Sigor@sysoev.ru 108720Sigor@sysoev.ru static nxt_sockaddr_t * 108820Sigor@sysoev.ru nxt_runtime_sockaddr_inet_parse(nxt_task_t *task, nxt_mem_pool_t *mp, 108926Sigor@sysoev.ru nxt_str_t *string) 109020Sigor@sysoev.ru { 109120Sigor@sysoev.ru u_char *p, *ip; 109220Sigor@sysoev.ru size_t length; 109326Sigor@sysoev.ru in_addr_t addr; 109420Sigor@sysoev.ru nxt_int_t port; 109520Sigor@sysoev.ru nxt_sockaddr_t *sa; 109620Sigor@sysoev.ru 109726Sigor@sysoev.ru addr = INADDR_ANY; 109820Sigor@sysoev.ru 109926Sigor@sysoev.ru length = string->length; 110026Sigor@sysoev.ru ip = string->start; 110120Sigor@sysoev.ru 110220Sigor@sysoev.ru p = nxt_memchr(ip, ':', length); 110320Sigor@sysoev.ru 110420Sigor@sysoev.ru if (p == NULL) { 110520Sigor@sysoev.ru 110620Sigor@sysoev.ru /* single value port, or address */ 110720Sigor@sysoev.ru 110820Sigor@sysoev.ru port = nxt_int_parse(ip, length); 110920Sigor@sysoev.ru 111020Sigor@sysoev.ru if (port > 0) { 111120Sigor@sysoev.ru /* "*:XX" */ 111220Sigor@sysoev.ru 111320Sigor@sysoev.ru if (port < 1 || port > 65535) { 111420Sigor@sysoev.ru goto invalid_port; 111520Sigor@sysoev.ru } 111620Sigor@sysoev.ru 111720Sigor@sysoev.ru } else { 111820Sigor@sysoev.ru /* "x.x.x.x" */ 111920Sigor@sysoev.ru 112026Sigor@sysoev.ru addr = nxt_inet_addr(ip, length); 112120Sigor@sysoev.ru 112226Sigor@sysoev.ru if (addr == INADDR_NONE) { 112320Sigor@sysoev.ru goto invalid_port; 112420Sigor@sysoev.ru } 112520Sigor@sysoev.ru 112620Sigor@sysoev.ru port = 8080; 112720Sigor@sysoev.ru } 112820Sigor@sysoev.ru 112920Sigor@sysoev.ru } else { 113020Sigor@sysoev.ru 113120Sigor@sysoev.ru /* x.x.x.x:XX */ 113220Sigor@sysoev.ru 113320Sigor@sysoev.ru p++; 113420Sigor@sysoev.ru length = (ip + length) - p; 113520Sigor@sysoev.ru port = nxt_int_parse(p, length); 113620Sigor@sysoev.ru 113720Sigor@sysoev.ru if (port < 1 || port > 65535) { 113820Sigor@sysoev.ru goto invalid_port; 113920Sigor@sysoev.ru } 114020Sigor@sysoev.ru 114120Sigor@sysoev.ru length = (p - 1) - ip; 114220Sigor@sysoev.ru 114320Sigor@sysoev.ru if (length != 1 || ip[0] != '*') { 114426Sigor@sysoev.ru addr = nxt_inet_addr(ip, length); 114520Sigor@sysoev.ru 114626Sigor@sysoev.ru if (addr == INADDR_NONE) { 114720Sigor@sysoev.ru goto invalid_addr; 114820Sigor@sysoev.ru } 114920Sigor@sysoev.ru 115020Sigor@sysoev.ru /* "x.x.x.x:XX" */ 115120Sigor@sysoev.ru } 115220Sigor@sysoev.ru } 115320Sigor@sysoev.ru 115420Sigor@sysoev.ru sa = nxt_sockaddr_alloc(mp, sizeof(struct sockaddr_in), 115520Sigor@sysoev.ru NXT_INET_ADDR_STR_LEN); 115620Sigor@sysoev.ru if (nxt_slow_path(sa == NULL)) { 115720Sigor@sysoev.ru return NULL; 115820Sigor@sysoev.ru } 115920Sigor@sysoev.ru 116020Sigor@sysoev.ru sa->type = SOCK_STREAM; 116120Sigor@sysoev.ru 116220Sigor@sysoev.ru sa->u.sockaddr_in.sin_family = AF_INET; 116320Sigor@sysoev.ru sa->u.sockaddr_in.sin_port = htons((in_port_t) port); 116426Sigor@sysoev.ru sa->u.sockaddr_in.sin_addr.s_addr = addr; 116520Sigor@sysoev.ru 116620Sigor@sysoev.ru return sa; 116720Sigor@sysoev.ru 116820Sigor@sysoev.ru invalid_port: 116920Sigor@sysoev.ru 117026Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid port in \"%V\"", string); 117120Sigor@sysoev.ru 117220Sigor@sysoev.ru return NULL; 117320Sigor@sysoev.ru 117420Sigor@sysoev.ru invalid_addr: 117520Sigor@sysoev.ru 117626Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "invalid address in \"%V\"", string); 117720Sigor@sysoev.ru 117820Sigor@sysoev.ru return NULL; 117920Sigor@sysoev.ru } 118020Sigor@sysoev.ru 118120Sigor@sysoev.ru 118220Sigor@sysoev.ru nxt_listen_socket_t * 118320Sigor@sysoev.ru nxt_runtime_listen_socket_add(nxt_runtime_t *rt, nxt_sockaddr_t *sa) 118420Sigor@sysoev.ru { 118520Sigor@sysoev.ru nxt_mem_pool_t *mp; 118620Sigor@sysoev.ru nxt_listen_socket_t *ls; 118720Sigor@sysoev.ru 118820Sigor@sysoev.ru ls = nxt_array_zero_add(rt->listen_sockets); 118920Sigor@sysoev.ru if (ls == NULL) { 119020Sigor@sysoev.ru return NULL; 119120Sigor@sysoev.ru } 119220Sigor@sysoev.ru 119320Sigor@sysoev.ru mp = rt->mem_pool; 119420Sigor@sysoev.ru 119520Sigor@sysoev.ru ls->sockaddr = nxt_sockaddr_create(mp, &sa->u.sockaddr, sa->socklen, 119620Sigor@sysoev.ru sa->length); 119720Sigor@sysoev.ru if (ls->sockaddr == NULL) { 119820Sigor@sysoev.ru return NULL; 119920Sigor@sysoev.ru } 120020Sigor@sysoev.ru 120120Sigor@sysoev.ru ls->sockaddr->type = sa->type; 120220Sigor@sysoev.ru 120320Sigor@sysoev.ru nxt_sockaddr_text(ls->sockaddr); 120420Sigor@sysoev.ru 120520Sigor@sysoev.ru ls->socket = -1; 120620Sigor@sysoev.ru ls->backlog = NXT_LISTEN_BACKLOG; 120720Sigor@sysoev.ru 120820Sigor@sysoev.ru return ls; 120920Sigor@sysoev.ru } 121020Sigor@sysoev.ru 121120Sigor@sysoev.ru 121220Sigor@sysoev.ru static nxt_int_t 121320Sigor@sysoev.ru nxt_runtime_hostname(nxt_task_t *task, nxt_runtime_t *rt) 121420Sigor@sysoev.ru { 121520Sigor@sysoev.ru size_t length; 121620Sigor@sysoev.ru char hostname[NXT_MAXHOSTNAMELEN + 1]; 121720Sigor@sysoev.ru 121820Sigor@sysoev.ru if (gethostname(hostname, NXT_MAXHOSTNAMELEN) != 0) { 121920Sigor@sysoev.ru nxt_log(task, NXT_LOG_CRIT, "gethostname() failed %E", nxt_errno); 122020Sigor@sysoev.ru return NXT_ERROR; 122120Sigor@sysoev.ru } 122220Sigor@sysoev.ru 122320Sigor@sysoev.ru /* 122420Sigor@sysoev.ru * Linux gethostname(2): 122520Sigor@sysoev.ru * 122620Sigor@sysoev.ru * If the null-terminated hostname is too large to fit, 122720Sigor@sysoev.ru * then the name is truncated, and no error is returned. 122820Sigor@sysoev.ru * 122920Sigor@sysoev.ru * For this reason an additional byte is reserved in the buffer. 123020Sigor@sysoev.ru */ 123120Sigor@sysoev.ru hostname[NXT_MAXHOSTNAMELEN] = '\0'; 123220Sigor@sysoev.ru 123320Sigor@sysoev.ru length = nxt_strlen(hostname); 123420Sigor@sysoev.ru rt->hostname.length = length; 123520Sigor@sysoev.ru 123620Sigor@sysoev.ru rt->hostname.start = nxt_mem_nalloc(rt->mem_pool, length); 123720Sigor@sysoev.ru 123820Sigor@sysoev.ru if (rt->hostname.start != NULL) { 123920Sigor@sysoev.ru nxt_memcpy_lowcase(rt->hostname.start, (u_char *) hostname, length); 124020Sigor@sysoev.ru return NXT_OK; 124120Sigor@sysoev.ru } 124220Sigor@sysoev.ru 124320Sigor@sysoev.ru return NXT_ERROR; 124420Sigor@sysoev.ru } 124520Sigor@sysoev.ru 124620Sigor@sysoev.ru 124720Sigor@sysoev.ru static nxt_int_t 124820Sigor@sysoev.ru nxt_runtime_log_files_init(nxt_runtime_t *rt) 124920Sigor@sysoev.ru { 125020Sigor@sysoev.ru nxt_file_t *file; 125120Sigor@sysoev.ru nxt_list_t *log_files; 125220Sigor@sysoev.ru 125320Sigor@sysoev.ru log_files = nxt_list_create(rt->mem_pool, 1, sizeof(nxt_file_t)); 125420Sigor@sysoev.ru 125520Sigor@sysoev.ru if (nxt_fast_path(log_files != NULL)) { 125620Sigor@sysoev.ru rt->log_files = log_files; 125720Sigor@sysoev.ru 125820Sigor@sysoev.ru /* Preallocate the main error_log. This allocation cannot fail. */ 125920Sigor@sysoev.ru file = nxt_list_zero_add(log_files); 126020Sigor@sysoev.ru 126120Sigor@sysoev.ru file->fd = NXT_FILE_INVALID; 126220Sigor@sysoev.ru file->log_level = NXT_LOG_CRIT; 126320Sigor@sysoev.ru 126420Sigor@sysoev.ru return NXT_OK; 126520Sigor@sysoev.ru } 126620Sigor@sysoev.ru 126720Sigor@sysoev.ru return NXT_ERROR; 126820Sigor@sysoev.ru } 126920Sigor@sysoev.ru 127020Sigor@sysoev.ru 127120Sigor@sysoev.ru nxt_file_t * 127220Sigor@sysoev.ru nxt_runtime_log_file_add(nxt_runtime_t *rt, nxt_str_t *name) 127320Sigor@sysoev.ru { 127420Sigor@sysoev.ru nxt_int_t ret; 127520Sigor@sysoev.ru nxt_str_t *prefix; 127620Sigor@sysoev.ru nxt_file_t *file; 127720Sigor@sysoev.ru nxt_file_name_str_t file_name; 127820Sigor@sysoev.ru 127920Sigor@sysoev.ru prefix = nxt_file_name_is_absolute(name->start) ? NULL : rt->prefix; 128020Sigor@sysoev.ru 128120Sigor@sysoev.ru ret = nxt_file_name_create(rt->mem_pool, &file_name, "%V%V%Z", 128220Sigor@sysoev.ru prefix, name); 128320Sigor@sysoev.ru 128420Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 128520Sigor@sysoev.ru return NULL; 128620Sigor@sysoev.ru } 128720Sigor@sysoev.ru 128820Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 128920Sigor@sysoev.ru 129020Sigor@sysoev.ru /* STUB: hardecoded case sensitive/insensitive. */ 129120Sigor@sysoev.ru 129220Sigor@sysoev.ru if (file->name != NULL 129320Sigor@sysoev.ru && nxt_file_name_eq(file->name, file_name.start)) 129420Sigor@sysoev.ru { 129520Sigor@sysoev.ru return file; 129620Sigor@sysoev.ru } 129720Sigor@sysoev.ru 129820Sigor@sysoev.ru } nxt_list_loop; 129920Sigor@sysoev.ru 130020Sigor@sysoev.ru file = nxt_list_zero_add(rt->log_files); 130120Sigor@sysoev.ru 130220Sigor@sysoev.ru if (nxt_slow_path(file == NULL)) { 130320Sigor@sysoev.ru return NULL; 130420Sigor@sysoev.ru } 130520Sigor@sysoev.ru 130620Sigor@sysoev.ru file->fd = NXT_FILE_INVALID; 130720Sigor@sysoev.ru file->log_level = NXT_LOG_CRIT; 130820Sigor@sysoev.ru file->name = file_name.start; 130920Sigor@sysoev.ru 131020Sigor@sysoev.ru return file; 131120Sigor@sysoev.ru } 131220Sigor@sysoev.ru 131320Sigor@sysoev.ru 131420Sigor@sysoev.ru static nxt_int_t 131520Sigor@sysoev.ru nxt_runtime_log_files_create(nxt_task_t *task, nxt_runtime_t *rt) 131620Sigor@sysoev.ru { 131720Sigor@sysoev.ru nxt_int_t ret; 131820Sigor@sysoev.ru nxt_file_t *file; 131920Sigor@sysoev.ru 132020Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 132120Sigor@sysoev.ru 132220Sigor@sysoev.ru ret = nxt_file_open(task, file, O_WRONLY | O_APPEND, O_CREAT, 132320Sigor@sysoev.ru NXT_FILE_OWNER_ACCESS); 132420Sigor@sysoev.ru 132520Sigor@sysoev.ru if (ret != NXT_OK) { 132620Sigor@sysoev.ru return NXT_ERROR; 132720Sigor@sysoev.ru } 132820Sigor@sysoev.ru 132920Sigor@sysoev.ru } nxt_list_loop; 133020Sigor@sysoev.ru 133120Sigor@sysoev.ru file = nxt_list_first(rt->log_files); 133220Sigor@sysoev.ru 133320Sigor@sysoev.ru return nxt_file_stderr(file); 133420Sigor@sysoev.ru } 133520Sigor@sysoev.ru 133620Sigor@sysoev.ru 133720Sigor@sysoev.ru nxt_int_t 133820Sigor@sysoev.ru nxt_runtime_listen_sockets_create(nxt_task_t *task, nxt_runtime_t *rt) 133920Sigor@sysoev.ru { 134020Sigor@sysoev.ru nxt_int_t ret; 134120Sigor@sysoev.ru nxt_uint_t c, p, ncurr, nprev; 134220Sigor@sysoev.ru nxt_listen_socket_t *curr, *prev; 134320Sigor@sysoev.ru 134420Sigor@sysoev.ru curr = rt->listen_sockets->elts; 134520Sigor@sysoev.ru ncurr = rt->listen_sockets->nelts; 134620Sigor@sysoev.ru 134720Sigor@sysoev.ru if (rt->inherited_sockets != NULL) { 134820Sigor@sysoev.ru prev = rt->inherited_sockets->elts; 134920Sigor@sysoev.ru nprev = rt->inherited_sockets->nelts; 135020Sigor@sysoev.ru 135120Sigor@sysoev.ru } else { 135220Sigor@sysoev.ru prev = NULL; 135320Sigor@sysoev.ru nprev = 0; 135420Sigor@sysoev.ru } 135520Sigor@sysoev.ru 135620Sigor@sysoev.ru for (c = 0; c < ncurr; c++) { 135720Sigor@sysoev.ru 135820Sigor@sysoev.ru for (p = 0; p < nprev; p++) { 135920Sigor@sysoev.ru 136020Sigor@sysoev.ru if (nxt_sockaddr_cmp(curr[c].sockaddr, prev[p].sockaddr)) { 136120Sigor@sysoev.ru 136220Sigor@sysoev.ru ret = nxt_listen_socket_update(task, &curr[c], &prev[p]); 136320Sigor@sysoev.ru if (ret != NXT_OK) { 136420Sigor@sysoev.ru return NXT_ERROR; 136520Sigor@sysoev.ru } 136620Sigor@sysoev.ru 136720Sigor@sysoev.ru goto next; 136820Sigor@sysoev.ru } 136920Sigor@sysoev.ru } 137020Sigor@sysoev.ru 137120Sigor@sysoev.ru if (nxt_listen_socket_create(task, &curr[c], 0) != NXT_OK) { 137220Sigor@sysoev.ru return NXT_ERROR; 137320Sigor@sysoev.ru } 137420Sigor@sysoev.ru 137520Sigor@sysoev.ru next: 137620Sigor@sysoev.ru 137720Sigor@sysoev.ru continue; 137820Sigor@sysoev.ru } 137920Sigor@sysoev.ru 138020Sigor@sysoev.ru return NXT_OK; 138120Sigor@sysoev.ru } 138220Sigor@sysoev.ru 138320Sigor@sysoev.ru 138420Sigor@sysoev.ru nxt_int_t 138520Sigor@sysoev.ru nxt_runtime_listen_sockets_enable(nxt_task_t *task, nxt_runtime_t *rt) 138620Sigor@sysoev.ru { 138720Sigor@sysoev.ru nxt_uint_t i, n; 138820Sigor@sysoev.ru nxt_listen_socket_t *ls; 138920Sigor@sysoev.ru 139020Sigor@sysoev.ru ls = rt->listen_sockets->elts; 139120Sigor@sysoev.ru n = rt->listen_sockets->nelts; 139220Sigor@sysoev.ru 139320Sigor@sysoev.ru for (i = 0; i < n; i++) { 139420Sigor@sysoev.ru if (ls[i].flags == NXT_NONBLOCK) { 139520Sigor@sysoev.ru if (nxt_event_conn_listen(task, &ls[i]) != NXT_OK) { 139620Sigor@sysoev.ru return NXT_ERROR; 139720Sigor@sysoev.ru } 139820Sigor@sysoev.ru } 139920Sigor@sysoev.ru } 140020Sigor@sysoev.ru 140120Sigor@sysoev.ru return NXT_OK; 140220Sigor@sysoev.ru } 140320Sigor@sysoev.ru 140420Sigor@sysoev.ru 140520Sigor@sysoev.ru nxt_str_t * 140620Sigor@sysoev.ru nxt_current_directory(nxt_mem_pool_t *mp) 140720Sigor@sysoev.ru { 140820Sigor@sysoev.ru size_t length; 140920Sigor@sysoev.ru u_char *p; 141020Sigor@sysoev.ru nxt_str_t *name; 141120Sigor@sysoev.ru char buf[NXT_MAX_PATH_LEN]; 141220Sigor@sysoev.ru 141320Sigor@sysoev.ru length = nxt_dir_current(buf, NXT_MAX_PATH_LEN); 141420Sigor@sysoev.ru 141520Sigor@sysoev.ru if (nxt_fast_path(length != 0)) { 141620Sigor@sysoev.ru name = nxt_str_alloc(mp, length + 1); 141720Sigor@sysoev.ru 141820Sigor@sysoev.ru if (nxt_fast_path(name != NULL)) { 141920Sigor@sysoev.ru p = nxt_cpymem(name->start, buf, length); 142020Sigor@sysoev.ru *p = '/'; 142120Sigor@sysoev.ru 142220Sigor@sysoev.ru return name; 142320Sigor@sysoev.ru } 142420Sigor@sysoev.ru } 142520Sigor@sysoev.ru 142620Sigor@sysoev.ru return NULL; 142720Sigor@sysoev.ru } 142820Sigor@sysoev.ru 142920Sigor@sysoev.ru 143020Sigor@sysoev.ru static nxt_int_t 143120Sigor@sysoev.ru nxt_runtime_pid_file_create(nxt_task_t *task, nxt_file_name_t *pid_file) 143220Sigor@sysoev.ru { 143320Sigor@sysoev.ru ssize_t length; 143420Sigor@sysoev.ru nxt_int_t n; 143520Sigor@sysoev.ru nxt_file_t file; 143620Sigor@sysoev.ru u_char pid[NXT_INT64_T_LEN + NXT_LINEFEED_SIZE]; 143720Sigor@sysoev.ru 143820Sigor@sysoev.ru nxt_memzero(&file, sizeof(nxt_file_t)); 143920Sigor@sysoev.ru 144020Sigor@sysoev.ru file.name = pid_file; 144120Sigor@sysoev.ru 144220Sigor@sysoev.ru n = nxt_file_open(task, &file, O_WRONLY, O_CREAT | O_TRUNC, 144320Sigor@sysoev.ru NXT_FILE_DEFAULT_ACCESS); 144420Sigor@sysoev.ru 144520Sigor@sysoev.ru if (n != NXT_OK) { 144620Sigor@sysoev.ru return NXT_ERROR; 144720Sigor@sysoev.ru } 144820Sigor@sysoev.ru 144920Sigor@sysoev.ru length = nxt_sprintf(pid, pid + sizeof(pid), "%PI%n", nxt_pid) - pid; 145020Sigor@sysoev.ru 145120Sigor@sysoev.ru if (nxt_file_write(&file, pid, length, 0) != length) { 145220Sigor@sysoev.ru return NXT_ERROR; 145320Sigor@sysoev.ru } 145420Sigor@sysoev.ru 145520Sigor@sysoev.ru nxt_file_close(task, &file); 145620Sigor@sysoev.ru 145720Sigor@sysoev.ru return NXT_OK; 145820Sigor@sysoev.ru } 145920Sigor@sysoev.ru 146020Sigor@sysoev.ru 146120Sigor@sysoev.ru nxt_process_t * 146242Smax.romanov@nginx.com nxt_runtime_process_new(nxt_runtime_t *rt) 146320Sigor@sysoev.ru { 146420Sigor@sysoev.ru nxt_process_t *process; 146520Sigor@sysoev.ru 146620Sigor@sysoev.ru /* TODO: memory failures. */ 146720Sigor@sysoev.ru 146842Smax.romanov@nginx.com process = nxt_mem_cache_zalloc0(rt->mem_pool, sizeof(nxt_process_t)); 146942Smax.romanov@nginx.com if (nxt_slow_path(process == NULL)) { 147042Smax.romanov@nginx.com return NULL; 147142Smax.romanov@nginx.com } 147242Smax.romanov@nginx.com 147342Smax.romanov@nginx.com nxt_queue_init(&process->ports); 147442Smax.romanov@nginx.com 147542Smax.romanov@nginx.com /* TODO each process should have it's own mem_pool for ports allocation */ 147642Smax.romanov@nginx.com process->mem_pool = rt->mem_pool; 147742Smax.romanov@nginx.com 147842Smax.romanov@nginx.com return process; 147942Smax.romanov@nginx.com } 148042Smax.romanov@nginx.com 148142Smax.romanov@nginx.com 148242Smax.romanov@nginx.com static nxt_int_t 148342Smax.romanov@nginx.com nxt_runtime_lvlhsh_pid_test(nxt_lvlhsh_query_t *lhq, void *data) 148442Smax.romanov@nginx.com { 148542Smax.romanov@nginx.com nxt_process_t *process; 148642Smax.romanov@nginx.com 148742Smax.romanov@nginx.com process = data; 148842Smax.romanov@nginx.com 148942Smax.romanov@nginx.com if (lhq->key.length == sizeof(nxt_pid_t) && 149042Smax.romanov@nginx.com *(nxt_pid_t *) lhq->key.start == process->pid) { 149142Smax.romanov@nginx.com return NXT_OK; 149242Smax.romanov@nginx.com } 149342Smax.romanov@nginx.com 149442Smax.romanov@nginx.com return NXT_DECLINED; 149542Smax.romanov@nginx.com } 149642Smax.romanov@nginx.com 149742Smax.romanov@nginx.com static const nxt_lvlhsh_proto_t lvlhsh_processes_proto nxt_aligned(64) = { 149842Smax.romanov@nginx.com NXT_LVLHSH_DEFAULT, 149942Smax.romanov@nginx.com 0, 150042Smax.romanov@nginx.com nxt_runtime_lvlhsh_pid_test, 150142Smax.romanov@nginx.com nxt_lvlhsh_alloc, 150242Smax.romanov@nginx.com nxt_lvlhsh_free, 150342Smax.romanov@nginx.com }; 150442Smax.romanov@nginx.com 150542Smax.romanov@nginx.com 150642Smax.romanov@nginx.com typedef struct { 150742Smax.romanov@nginx.com nxt_pid_t pid; 150842Smax.romanov@nginx.com nxt_port_id_t port_id; 150942Smax.romanov@nginx.com } nxt_pid_port_id_t; 151042Smax.romanov@nginx.com 151142Smax.romanov@nginx.com static nxt_int_t 151242Smax.romanov@nginx.com nxt_runtime_lvlhsh_port_test(nxt_lvlhsh_query_t *lhq, void *data) 151342Smax.romanov@nginx.com { 151442Smax.romanov@nginx.com nxt_port_t *port; 151542Smax.romanov@nginx.com nxt_pid_port_id_t *pid_port_id; 151642Smax.romanov@nginx.com 151742Smax.romanov@nginx.com port = data; 151842Smax.romanov@nginx.com pid_port_id = (nxt_pid_port_id_t *) lhq->key.start; 151942Smax.romanov@nginx.com 152042Smax.romanov@nginx.com if (lhq->key.length == sizeof(nxt_pid_port_id_t) && 152142Smax.romanov@nginx.com pid_port_id->pid == port->pid && 152242Smax.romanov@nginx.com pid_port_id->port_id == port->id) { 152342Smax.romanov@nginx.com return NXT_OK; 152442Smax.romanov@nginx.com } 152542Smax.romanov@nginx.com 152642Smax.romanov@nginx.com return NXT_DECLINED; 152742Smax.romanov@nginx.com } 152842Smax.romanov@nginx.com 152942Smax.romanov@nginx.com static const nxt_lvlhsh_proto_t lvlhsh_ports_proto nxt_aligned(64) = { 153042Smax.romanov@nginx.com NXT_LVLHSH_DEFAULT, 153142Smax.romanov@nginx.com 0, 153242Smax.romanov@nginx.com nxt_runtime_lvlhsh_port_test, 153342Smax.romanov@nginx.com nxt_lvlhsh_alloc, 153442Smax.romanov@nginx.com nxt_lvlhsh_free, 153542Smax.romanov@nginx.com }; 153642Smax.romanov@nginx.com 153742Smax.romanov@nginx.com 153842Smax.romanov@nginx.com nxt_process_t * 153942Smax.romanov@nginx.com nxt_runtime_process_find(nxt_runtime_t *rt, nxt_pid_t pid) 154042Smax.romanov@nginx.com { 154142Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 154242Smax.romanov@nginx.com 154342Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&pid, sizeof(pid)); 154442Smax.romanov@nginx.com lhq.key.length = sizeof(pid); 154542Smax.romanov@nginx.com lhq.key.start = (u_char *) &pid; 154642Smax.romanov@nginx.com lhq.proto = &lvlhsh_processes_proto; 154742Smax.romanov@nginx.com 154842Smax.romanov@nginx.com /* TODO lock processes */ 154942Smax.romanov@nginx.com 155042Smax.romanov@nginx.com if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) { 155142Smax.romanov@nginx.com nxt_thread_log_debug("process %PI found", pid); 155242Smax.romanov@nginx.com return lhq.value; 155342Smax.romanov@nginx.com } 155442Smax.romanov@nginx.com 155542Smax.romanov@nginx.com nxt_thread_log_debug("process %PI not found", pid); 155642Smax.romanov@nginx.com 155742Smax.romanov@nginx.com return NULL; 155842Smax.romanov@nginx.com } 155942Smax.romanov@nginx.com 156042Smax.romanov@nginx.com 156142Smax.romanov@nginx.com nxt_process_t * 156242Smax.romanov@nginx.com nxt_runtime_process_get(nxt_runtime_t *rt, nxt_pid_t pid) 156342Smax.romanov@nginx.com { 156442Smax.romanov@nginx.com nxt_process_t *process; 156542Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 156642Smax.romanov@nginx.com 156742Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&pid, sizeof(pid)); 156842Smax.romanov@nginx.com lhq.key.length = sizeof(pid); 156942Smax.romanov@nginx.com lhq.key.start = (u_char *) &pid; 157042Smax.romanov@nginx.com lhq.proto = &lvlhsh_processes_proto; 157142Smax.romanov@nginx.com 157242Smax.romanov@nginx.com /* TODO lock processes */ 157342Smax.romanov@nginx.com 157442Smax.romanov@nginx.com if (nxt_lvlhsh_find(&rt->processes, &lhq) == NXT_OK) { 157542Smax.romanov@nginx.com nxt_thread_log_debug("process %PI found", pid); 157642Smax.romanov@nginx.com return lhq.value; 157742Smax.romanov@nginx.com } 157842Smax.romanov@nginx.com 157942Smax.romanov@nginx.com process = nxt_runtime_process_new(rt); 158020Sigor@sysoev.ru if (nxt_slow_path(process == NULL)) { 158120Sigor@sysoev.ru return NULL; 158220Sigor@sysoev.ru } 158320Sigor@sysoev.ru 158442Smax.romanov@nginx.com process->pid = pid; 158542Smax.romanov@nginx.com 158642Smax.romanov@nginx.com lhq.replace = 0; 158742Smax.romanov@nginx.com lhq.value = process; 158842Smax.romanov@nginx.com lhq.pool = rt->mem_pool; 158942Smax.romanov@nginx.com 159042Smax.romanov@nginx.com switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) { 159142Smax.romanov@nginx.com 159242Smax.romanov@nginx.com case NXT_OK: 159342Smax.romanov@nginx.com if (rt->nprocesses == 0) { 159442Smax.romanov@nginx.com rt->mprocess = process; 159542Smax.romanov@nginx.com } 159642Smax.romanov@nginx.com 159742Smax.romanov@nginx.com rt->nprocesses++; 159842Smax.romanov@nginx.com 159942Smax.romanov@nginx.com nxt_thread_log_debug("process %PI insert", pid); 160042Smax.romanov@nginx.com break; 160142Smax.romanov@nginx.com 160242Smax.romanov@nginx.com default: 160342Smax.romanov@nginx.com nxt_thread_log_debug("process %PI insert failed", pid); 160442Smax.romanov@nginx.com break; 160520Sigor@sysoev.ru } 160620Sigor@sysoev.ru 160720Sigor@sysoev.ru return process; 160820Sigor@sysoev.ru } 160942Smax.romanov@nginx.com 161042Smax.romanov@nginx.com 161142Smax.romanov@nginx.com void 161242Smax.romanov@nginx.com nxt_runtime_process_add(nxt_runtime_t *rt, nxt_process_t *process) 161342Smax.romanov@nginx.com { 161442Smax.romanov@nginx.com nxt_port_t *port; 161542Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 161642Smax.romanov@nginx.com 161742Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&process->pid, sizeof(process->pid)); 161842Smax.romanov@nginx.com lhq.key.length = sizeof(process->pid); 161942Smax.romanov@nginx.com lhq.key.start = (u_char *) &process->pid; 162042Smax.romanov@nginx.com lhq.proto = &lvlhsh_processes_proto; 162142Smax.romanov@nginx.com lhq.replace = 0; 162242Smax.romanov@nginx.com lhq.value = process; 162342Smax.romanov@nginx.com lhq.pool = rt->mem_pool; 162442Smax.romanov@nginx.com 162542Smax.romanov@nginx.com /* TODO lock processes */ 162642Smax.romanov@nginx.com 162742Smax.romanov@nginx.com switch (nxt_lvlhsh_insert(&rt->processes, &lhq)) { 162842Smax.romanov@nginx.com 162942Smax.romanov@nginx.com case NXT_OK: 163042Smax.romanov@nginx.com if (rt->nprocesses == 0) { 163142Smax.romanov@nginx.com rt->mprocess = process; 163242Smax.romanov@nginx.com } 163342Smax.romanov@nginx.com 163442Smax.romanov@nginx.com rt->nprocesses++; 163542Smax.romanov@nginx.com 163642Smax.romanov@nginx.com nxt_process_port_each(process, port) { 163742Smax.romanov@nginx.com 163842Smax.romanov@nginx.com nxt_runtime_port_add(rt, port); 163942Smax.romanov@nginx.com 164042Smax.romanov@nginx.com } nxt_process_port_loop; 164142Smax.romanov@nginx.com 164242Smax.romanov@nginx.com break; 164342Smax.romanov@nginx.com 164442Smax.romanov@nginx.com default: 164542Smax.romanov@nginx.com break; 164642Smax.romanov@nginx.com } 164742Smax.romanov@nginx.com } 164842Smax.romanov@nginx.com 164942Smax.romanov@nginx.com 165042Smax.romanov@nginx.com void 165142Smax.romanov@nginx.com nxt_runtime_process_remove(nxt_runtime_t *rt, nxt_process_t *process) 165242Smax.romanov@nginx.com { 165342Smax.romanov@nginx.com nxt_port_t *port; 165442Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 165542Smax.romanov@nginx.com 165642Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&process->pid, sizeof(process->pid)); 165742Smax.romanov@nginx.com lhq.key.length = sizeof(process->pid); 165842Smax.romanov@nginx.com lhq.key.start = (u_char *) &process->pid; 165942Smax.romanov@nginx.com lhq.proto = &lvlhsh_processes_proto; 166042Smax.romanov@nginx.com lhq.replace = 0; 166142Smax.romanov@nginx.com lhq.value = process; 166242Smax.romanov@nginx.com lhq.pool = rt->mem_pool; 166342Smax.romanov@nginx.com 166442Smax.romanov@nginx.com /* TODO lock processes */ 166542Smax.romanov@nginx.com 166642Smax.romanov@nginx.com switch (nxt_lvlhsh_delete(&rt->processes, &lhq)) { 166742Smax.romanov@nginx.com 166842Smax.romanov@nginx.com case NXT_OK: 166942Smax.romanov@nginx.com rt->nprocesses--; 167042Smax.romanov@nginx.com 167142Smax.romanov@nginx.com nxt_process_port_each(process, port) { 167242Smax.romanov@nginx.com 167342Smax.romanov@nginx.com nxt_runtime_port_remove(rt, port); 167442Smax.romanov@nginx.com 167542Smax.romanov@nginx.com } nxt_process_port_loop; 167642Smax.romanov@nginx.com 167742Smax.romanov@nginx.com break; 167842Smax.romanov@nginx.com 167942Smax.romanov@nginx.com default: 168042Smax.romanov@nginx.com break; 168142Smax.romanov@nginx.com } 168242Smax.romanov@nginx.com } 168342Smax.romanov@nginx.com 168442Smax.romanov@nginx.com 168542Smax.romanov@nginx.com nxt_process_t * 168642Smax.romanov@nginx.com nxt_runtime_process_first(nxt_runtime_t *rt, nxt_lvlhsh_each_t *lhe) 168742Smax.romanov@nginx.com { 168842Smax.romanov@nginx.com nxt_memzero(lhe, sizeof(nxt_lvlhsh_each_t)); 168942Smax.romanov@nginx.com 169042Smax.romanov@nginx.com lhe->proto = &lvlhsh_processes_proto; 169142Smax.romanov@nginx.com 169242Smax.romanov@nginx.com return nxt_runtime_process_next(rt, lhe); 169342Smax.romanov@nginx.com } 169442Smax.romanov@nginx.com 169542Smax.romanov@nginx.com 169642Smax.romanov@nginx.com void 169742Smax.romanov@nginx.com nxt_runtime_port_add(nxt_runtime_t *rt, nxt_port_t *port) 169842Smax.romanov@nginx.com { 169942Smax.romanov@nginx.com nxt_pid_port_id_t pid_port; 170042Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 170142Smax.romanov@nginx.com 170242Smax.romanov@nginx.com pid_port.pid = port->pid; 170342Smax.romanov@nginx.com pid_port.port_id = port->id; 170442Smax.romanov@nginx.com 170542Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&pid_port, sizeof(pid_port)); 170642Smax.romanov@nginx.com lhq.key.length = sizeof(pid_port); 170742Smax.romanov@nginx.com lhq.key.start = (u_char *) &pid_port; 170842Smax.romanov@nginx.com lhq.proto = &lvlhsh_ports_proto; 170942Smax.romanov@nginx.com lhq.replace = 0; 171042Smax.romanov@nginx.com lhq.value = port; 171142Smax.romanov@nginx.com lhq.pool = rt->mem_pool; 171242Smax.romanov@nginx.com 171342Smax.romanov@nginx.com /* TODO lock ports */ 171442Smax.romanov@nginx.com 171542Smax.romanov@nginx.com switch (nxt_lvlhsh_insert(&rt->ports, &lhq)) { 171642Smax.romanov@nginx.com 171742Smax.romanov@nginx.com case NXT_OK: 171842Smax.romanov@nginx.com break; 171942Smax.romanov@nginx.com 172042Smax.romanov@nginx.com default: 172142Smax.romanov@nginx.com break; 172242Smax.romanov@nginx.com } 172342Smax.romanov@nginx.com } 172442Smax.romanov@nginx.com 172542Smax.romanov@nginx.com 172642Smax.romanov@nginx.com void 172742Smax.romanov@nginx.com nxt_runtime_port_remove(nxt_runtime_t *rt, nxt_port_t *port) 172842Smax.romanov@nginx.com { 172942Smax.romanov@nginx.com nxt_pid_port_id_t pid_port; 173042Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 173142Smax.romanov@nginx.com 173242Smax.romanov@nginx.com pid_port.pid = port->pid; 173342Smax.romanov@nginx.com pid_port.port_id = port->id; 173442Smax.romanov@nginx.com 173542Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&pid_port, sizeof(pid_port)); 173642Smax.romanov@nginx.com lhq.key.length = sizeof(pid_port); 173742Smax.romanov@nginx.com lhq.key.start = (u_char *) &pid_port; 173842Smax.romanov@nginx.com lhq.proto = &lvlhsh_ports_proto; 173942Smax.romanov@nginx.com lhq.replace = 0; 174042Smax.romanov@nginx.com lhq.value = port; 174142Smax.romanov@nginx.com lhq.pool = rt->mem_pool; 174242Smax.romanov@nginx.com 174342Smax.romanov@nginx.com /* TODO lock ports */ 174442Smax.romanov@nginx.com 174542Smax.romanov@nginx.com switch (nxt_lvlhsh_delete(&rt->ports, &lhq)) { 174642Smax.romanov@nginx.com 174742Smax.romanov@nginx.com case NXT_OK: 174842Smax.romanov@nginx.com break; 174942Smax.romanov@nginx.com 175042Smax.romanov@nginx.com default: 175142Smax.romanov@nginx.com break; 175242Smax.romanov@nginx.com } 175342Smax.romanov@nginx.com } 175442Smax.romanov@nginx.com 175542Smax.romanov@nginx.com 175642Smax.romanov@nginx.com nxt_port_t * 175742Smax.romanov@nginx.com nxt_runtime_port_find(nxt_runtime_t *rt, nxt_pid_t pid, 175842Smax.romanov@nginx.com nxt_port_id_t port_id) 175942Smax.romanov@nginx.com { 176042Smax.romanov@nginx.com nxt_pid_port_id_t pid_port; 176142Smax.romanov@nginx.com nxt_lvlhsh_query_t lhq; 176242Smax.romanov@nginx.com 176342Smax.romanov@nginx.com pid_port.pid = pid; 176442Smax.romanov@nginx.com pid_port.port_id = port_id; 176542Smax.romanov@nginx.com 176642Smax.romanov@nginx.com lhq.key_hash = nxt_murmur_hash2(&pid_port, sizeof(pid_port)); 176742Smax.romanov@nginx.com lhq.key.length = sizeof(pid_port); 176842Smax.romanov@nginx.com lhq.key.start = (u_char *) &pid_port; 176942Smax.romanov@nginx.com lhq.proto = &lvlhsh_ports_proto; 177042Smax.romanov@nginx.com 177142Smax.romanov@nginx.com /* TODO lock ports */ 177242Smax.romanov@nginx.com 177342Smax.romanov@nginx.com if (nxt_lvlhsh_find(&rt->ports, &lhq) == NXT_OK) { 177442Smax.romanov@nginx.com nxt_thread_log_debug("process port (%PI, %d) found", pid, port_id); 177542Smax.romanov@nginx.com return lhq.value; 177642Smax.romanov@nginx.com } 177742Smax.romanov@nginx.com 177842Smax.romanov@nginx.com nxt_thread_log_debug("process port (%PI, %d) not found", pid, port_id); 177942Smax.romanov@nginx.com 178042Smax.romanov@nginx.com return NULL; 178142Smax.romanov@nginx.com } 1782