1240Sigor@sysoev.ru 2240Sigor@sysoev.ru /* 3240Sigor@sysoev.ru * Copyright (C) Igor Sysoev 4240Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 5240Sigor@sysoev.ru */ 6240Sigor@sysoev.ru 7240Sigor@sysoev.ru #include <nxt_main.h> 8240Sigor@sysoev.ru #include <nxt_runtime.h> 9240Sigor@sysoev.ru #include <nxt_port.h> 10240Sigor@sysoev.ru #include <nxt_main_process.h> 11240Sigor@sysoev.ru #include <nxt_conf.h> 12444Sigor@sysoev.ru #include <nxt_router.h> 13774Svbart@nginx.com #if (NXT_TLS) 14774Svbart@nginx.com #include <nxt_cert.h> 15774Svbart@nginx.com #endif 16240Sigor@sysoev.ru 17240Sigor@sysoev.ru 18240Sigor@sysoev.ru typedef struct { 19240Sigor@sysoev.ru nxt_socket_t socket; 20240Sigor@sysoev.ru nxt_socket_error_t error; 21240Sigor@sysoev.ru u_char *start; 22240Sigor@sysoev.ru u_char *end; 23240Sigor@sysoev.ru } nxt_listening_socket_t; 24240Sigor@sysoev.ru 25240Sigor@sysoev.ru 26510Salexander.borisov@nginx.com typedef struct { 27536Svbart@nginx.com nxt_uint_t size; 28536Svbart@nginx.com nxt_conf_map_t *map; 29546Smax.romanov@nginx.com } nxt_conf_app_map_t; 30510Salexander.borisov@nginx.com 31510Salexander.borisov@nginx.com 321302St.nateldemoura@f5.com extern nxt_port_handlers_t nxt_controller_process_port_handlers; 331302St.nateldemoura@f5.com extern nxt_port_handlers_t nxt_router_process_port_handlers; 341302St.nateldemoura@f5.com 351302St.nateldemoura@f5.com 36240Sigor@sysoev.ru static nxt_int_t nxt_main_process_port_create(nxt_task_t *task, 37240Sigor@sysoev.ru nxt_runtime_t *rt); 38240Sigor@sysoev.ru static void nxt_main_process_title(nxt_task_t *task); 39240Sigor@sysoev.ru static nxt_int_t nxt_main_start_controller_process(nxt_task_t *task, 40240Sigor@sysoev.ru nxt_runtime_t *rt); 41368Svbart@nginx.com static nxt_int_t nxt_main_create_controller_process(nxt_task_t *task, 42368Svbart@nginx.com nxt_runtime_t *rt, nxt_process_init_t *init); 431302St.nateldemoura@f5.com static nxt_int_t nxt_main_create_router_process(nxt_task_t *task, nxt_runtime_t *rt, 441302St.nateldemoura@f5.com nxt_process_init_t *init); 45240Sigor@sysoev.ru static nxt_int_t nxt_main_start_router_process(nxt_task_t *task, 46240Sigor@sysoev.ru nxt_runtime_t *rt); 47240Sigor@sysoev.ru static nxt_int_t nxt_main_start_discovery_process(nxt_task_t *task, 48240Sigor@sysoev.ru nxt_runtime_t *rt); 49240Sigor@sysoev.ru static nxt_int_t nxt_main_start_worker_process(nxt_task_t *task, 50240Sigor@sysoev.ru nxt_runtime_t *rt, nxt_common_app_conf_t *app_conf, uint32_t stream); 51240Sigor@sysoev.ru static nxt_int_t nxt_main_create_worker_process(nxt_task_t *task, 52240Sigor@sysoev.ru nxt_runtime_t *rt, nxt_process_init_t *init); 53240Sigor@sysoev.ru static void nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, 54240Sigor@sysoev.ru void *data); 55240Sigor@sysoev.ru static void nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, 56240Sigor@sysoev.ru void *data); 57240Sigor@sysoev.ru static void nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, 58240Sigor@sysoev.ru void *data); 59240Sigor@sysoev.ru static void nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, 60240Sigor@sysoev.ru void *data); 61944Sigor@sysoev.ru static void nxt_main_process_signal_handler(nxt_task_t *task, void *obj, 62944Sigor@sysoev.ru void *data); 63240Sigor@sysoev.ru static void nxt_main_cleanup_worker_process(nxt_task_t *task, nxt_pid_t pid); 64754Smax.romanov@nginx.com static void nxt_main_stop_worker_processes(nxt_task_t *task, nxt_runtime_t *rt); 65240Sigor@sysoev.ru static void nxt_main_port_socket_handler(nxt_task_t *task, 66240Sigor@sysoev.ru nxt_port_recv_msg_t *msg); 67240Sigor@sysoev.ru static nxt_int_t nxt_main_listening_socket(nxt_sockaddr_t *sa, 68240Sigor@sysoev.ru nxt_listening_socket_t *ls); 69240Sigor@sysoev.ru static void nxt_main_port_modules_handler(nxt_task_t *task, 70240Sigor@sysoev.ru nxt_port_recv_msg_t *msg); 71240Sigor@sysoev.ru static int nxt_cdecl nxt_app_lang_compare(const void *v1, const void *v2); 72314Svbart@nginx.com static void nxt_main_port_conf_store_handler(nxt_task_t *task, 73314Svbart@nginx.com nxt_port_recv_msg_t *msg); 74630Svbart@nginx.com static void nxt_main_port_access_log_handler(nxt_task_t *task, 75630Svbart@nginx.com nxt_port_recv_msg_t *msg); 761302St.nateldemoura@f5.com static nxt_process_init_t *nxt_process_init_create(nxt_task_t *task, 771302St.nateldemoura@f5.com nxt_process_type_t type, const nxt_str_t *name); 781302St.nateldemoura@f5.com static nxt_int_t nxt_process_init_name_set(nxt_process_init_t *init, 791302St.nateldemoura@f5.com nxt_process_type_t type, const nxt_str_t *name); 801302St.nateldemoura@f5.com static nxt_int_t nxt_process_init_creds_set(nxt_task_t *task, 811302St.nateldemoura@f5.com nxt_process_init_t *init, nxt_str_t *user, nxt_str_t *group); 82240Sigor@sysoev.ru 831306St.nateldemoura@f5.com static nxt_int_t nxt_init_isolation(nxt_task_t *task, 841306St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_init_t *init); 851306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 861306St.nateldemoura@f5.com static nxt_int_t nxt_init_clone_flags(nxt_task_t *task, 871306St.nateldemoura@f5.com nxt_conf_value_t *namespaces, nxt_process_init_t *init); 881306St.nateldemoura@f5.com #endif 891306St.nateldemoura@f5.com 901306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 911306St.nateldemoura@f5.com static nxt_int_t nxt_init_isolation_creds(nxt_task_t *task, 921306St.nateldemoura@f5.com nxt_conf_value_t *isolation, nxt_process_init_t *init); 931306St.nateldemoura@f5.com static nxt_int_t nxt_init_vldt_isolation_creds(nxt_task_t *task, 941306St.nateldemoura@f5.com nxt_process_init_t *init); 951306St.nateldemoura@f5.com static nxt_int_t nxt_init_isolation_credential_map(nxt_task_t *task, 961306St.nateldemoura@f5.com nxt_mp_t *mem_pool, nxt_conf_value_t *map_array, 971306St.nateldemoura@f5.com nxt_clone_credential_map_t *map); 981306St.nateldemoura@f5.com #endif 99240Sigor@sysoev.ru 100240Sigor@sysoev.ru const nxt_sig_event_t nxt_main_process_signals[] = { 101944Sigor@sysoev.ru nxt_event_signal(SIGHUP, nxt_main_process_signal_handler), 102240Sigor@sysoev.ru nxt_event_signal(SIGINT, nxt_main_process_sigterm_handler), 103240Sigor@sysoev.ru nxt_event_signal(SIGQUIT, nxt_main_process_sigquit_handler), 104240Sigor@sysoev.ru nxt_event_signal(SIGTERM, nxt_main_process_sigterm_handler), 105240Sigor@sysoev.ru nxt_event_signal(SIGCHLD, nxt_main_process_sigchld_handler), 106240Sigor@sysoev.ru nxt_event_signal(SIGUSR1, nxt_main_process_sigusr1_handler), 107240Sigor@sysoev.ru nxt_event_signal_end, 108240Sigor@sysoev.ru }; 109240Sigor@sysoev.ru 110240Sigor@sysoev.ru 1111302St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_app_process_port_handlers = { 1121302St.nateldemoura@f5.com .new_port = nxt_port_new_port_handler, 1131302St.nateldemoura@f5.com .change_file = nxt_port_change_log_file_handler, 1141302St.nateldemoura@f5.com .mmap = nxt_port_mmap_handler, 1151302St.nateldemoura@f5.com .remove_pid = nxt_port_remove_pid_handler, 1161302St.nateldemoura@f5.com }; 1171302St.nateldemoura@f5.com 1181302St.nateldemoura@f5.com 1191302St.nateldemoura@f5.com static const nxt_port_handlers_t nxt_discovery_process_port_handlers = { 1201302St.nateldemoura@f5.com .quit = nxt_worker_process_quit_handler, 1211302St.nateldemoura@f5.com .new_port = nxt_port_new_port_handler, 1221302St.nateldemoura@f5.com .change_file = nxt_port_change_log_file_handler, 1231302St.nateldemoura@f5.com .mmap = nxt_port_mmap_handler, 1241302St.nateldemoura@f5.com .data = nxt_port_data_handler, 1251302St.nateldemoura@f5.com .remove_pid = nxt_port_remove_pid_handler, 1261302St.nateldemoura@f5.com .rpc_ready = nxt_port_rpc_handler, 1271302St.nateldemoura@f5.com .rpc_error = nxt_port_rpc_handler, 1281302St.nateldemoura@f5.com }; 1291302St.nateldemoura@f5.com 1301302St.nateldemoura@f5.com 1311302St.nateldemoura@f5.com static const nxt_port_handlers_t *nxt_process_port_handlers[NXT_PROCESS_MAX] = 1321302St.nateldemoura@f5.com { 1331302St.nateldemoura@f5.com NULL, 1341302St.nateldemoura@f5.com &nxt_discovery_process_port_handlers, 1351302St.nateldemoura@f5.com &nxt_controller_process_port_handlers, 1361302St.nateldemoura@f5.com &nxt_router_process_port_handlers, 1371302St.nateldemoura@f5.com &nxt_app_process_port_handlers 1381302St.nateldemoura@f5.com }; 1391302St.nateldemoura@f5.com 1401302St.nateldemoura@f5.com 1411302St.nateldemoura@f5.com static const nxt_process_start_t nxt_process_starts[NXT_PROCESS_MAX] = { 1421302St.nateldemoura@f5.com NULL, 1431302St.nateldemoura@f5.com nxt_discovery_start, 1441302St.nateldemoura@f5.com nxt_controller_start, 1451302St.nateldemoura@f5.com nxt_router_start, 1461302St.nateldemoura@f5.com nxt_app_start 1471302St.nateldemoura@f5.com }; 1481302St.nateldemoura@f5.com 1491302St.nateldemoura@f5.com 1501302St.nateldemoura@f5.com static const nxt_process_restart_t nxt_process_restarts[NXT_PROCESS_MAX] = { 1511302St.nateldemoura@f5.com NULL, 1521302St.nateldemoura@f5.com NULL, 1531302St.nateldemoura@f5.com &nxt_main_create_controller_process, 1541302St.nateldemoura@f5.com &nxt_main_create_router_process, 1551302St.nateldemoura@f5.com NULL 1561302St.nateldemoura@f5.com }; 1571302St.nateldemoura@f5.com 1581302St.nateldemoura@f5.com 159240Sigor@sysoev.ru static nxt_bool_t nxt_exiting; 160240Sigor@sysoev.ru 161240Sigor@sysoev.ru 162240Sigor@sysoev.ru nxt_int_t 163240Sigor@sysoev.ru nxt_main_process_start(nxt_thread_t *thr, nxt_task_t *task, 164240Sigor@sysoev.ru nxt_runtime_t *rt) 165240Sigor@sysoev.ru { 166696Sigor@sysoev.ru rt->type = NXT_PROCESS_MAIN; 167240Sigor@sysoev.ru 168240Sigor@sysoev.ru if (nxt_main_process_port_create(task, rt) != NXT_OK) { 169240Sigor@sysoev.ru return NXT_ERROR; 170240Sigor@sysoev.ru } 171240Sigor@sysoev.ru 172240Sigor@sysoev.ru nxt_main_process_title(task); 173240Sigor@sysoev.ru 174240Sigor@sysoev.ru /* 175240Sigor@sysoev.ru * The dicsovery process will send a message processed by 176240Sigor@sysoev.ru * nxt_main_port_modules_handler() which starts the controller 177240Sigor@sysoev.ru * and router processes. 178240Sigor@sysoev.ru */ 179240Sigor@sysoev.ru return nxt_main_start_discovery_process(task, rt); 180240Sigor@sysoev.ru } 181240Sigor@sysoev.ru 182240Sigor@sysoev.ru 183240Sigor@sysoev.ru static nxt_conf_map_t nxt_common_app_conf[] = { 184240Sigor@sysoev.ru { 185240Sigor@sysoev.ru nxt_string("type"), 186240Sigor@sysoev.ru NXT_CONF_MAP_STR, 187240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, type), 188240Sigor@sysoev.ru }, 189240Sigor@sysoev.ru 190240Sigor@sysoev.ru { 191240Sigor@sysoev.ru nxt_string("user"), 192240Sigor@sysoev.ru NXT_CONF_MAP_STR, 193240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, user), 194240Sigor@sysoev.ru }, 195240Sigor@sysoev.ru 196240Sigor@sysoev.ru { 197240Sigor@sysoev.ru nxt_string("group"), 198240Sigor@sysoev.ru NXT_CONF_MAP_STR, 199240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, group), 200240Sigor@sysoev.ru }, 201240Sigor@sysoev.ru 202240Sigor@sysoev.ru { 203271Smax.romanov@nginx.com nxt_string("working_directory"), 204271Smax.romanov@nginx.com NXT_CONF_MAP_CSTRZ, 205271Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, working_directory), 206271Smax.romanov@nginx.com }, 207678Svbart@nginx.com 208678Svbart@nginx.com { 209678Svbart@nginx.com nxt_string("environment"), 210678Svbart@nginx.com NXT_CONF_MAP_PTR, 211678Svbart@nginx.com offsetof(nxt_common_app_conf_t, environment), 212678Svbart@nginx.com }, 2131182St.nateldemoura@f5.com 2141182St.nateldemoura@f5.com { 2151182St.nateldemoura@f5.com nxt_string("isolation"), 2161182St.nateldemoura@f5.com NXT_CONF_MAP_PTR, 2171182St.nateldemoura@f5.com offsetof(nxt_common_app_conf_t, isolation), 218*1320Smax.romanov@nginx.com }, 219*1320Smax.romanov@nginx.com 220*1320Smax.romanov@nginx.com { 221*1320Smax.romanov@nginx.com nxt_string("limits"), 222*1320Smax.romanov@nginx.com NXT_CONF_MAP_PTR, 223*1320Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, limits), 224*1320Smax.romanov@nginx.com }, 225*1320Smax.romanov@nginx.com 226*1320Smax.romanov@nginx.com }; 227*1320Smax.romanov@nginx.com 228*1320Smax.romanov@nginx.com 229*1320Smax.romanov@nginx.com static nxt_conf_map_t nxt_common_app_limits_conf[] = { 230*1320Smax.romanov@nginx.com { 231*1320Smax.romanov@nginx.com nxt_string("shm"), 232*1320Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 233*1320Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, shm_limit), 234*1320Smax.romanov@nginx.com }, 235*1320Smax.romanov@nginx.com 236510Salexander.borisov@nginx.com }; 237271Smax.romanov@nginx.com 238510Salexander.borisov@nginx.com 239804Svbart@nginx.com static nxt_conf_map_t nxt_external_app_conf[] = { 240804Svbart@nginx.com { 241804Svbart@nginx.com nxt_string("executable"), 242804Svbart@nginx.com NXT_CONF_MAP_CSTRZ, 243804Svbart@nginx.com offsetof(nxt_common_app_conf_t, u.external.executable), 244804Svbart@nginx.com }, 245804Svbart@nginx.com 246804Svbart@nginx.com { 247804Svbart@nginx.com nxt_string("arguments"), 248804Svbart@nginx.com NXT_CONF_MAP_PTR, 249804Svbart@nginx.com offsetof(nxt_common_app_conf_t, u.external.arguments), 250804Svbart@nginx.com }, 251804Svbart@nginx.com 252804Svbart@nginx.com }; 253804Svbart@nginx.com 254804Svbart@nginx.com 255546Smax.romanov@nginx.com static nxt_conf_map_t nxt_python_app_conf[] = { 256271Smax.romanov@nginx.com { 257394Smax.romanov@nginx.com nxt_string("home"), 258394Smax.romanov@nginx.com NXT_CONF_MAP_CSTRZ, 259394Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.python.home), 260394Smax.romanov@nginx.com }, 261394Smax.romanov@nginx.com 262394Smax.romanov@nginx.com { 263240Sigor@sysoev.ru nxt_string("path"), 264240Sigor@sysoev.ru NXT_CONF_MAP_STR, 265240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, u.python.path), 266240Sigor@sysoev.ru }, 267240Sigor@sysoev.ru 268240Sigor@sysoev.ru { 269240Sigor@sysoev.ru nxt_string("module"), 270240Sigor@sysoev.ru NXT_CONF_MAP_STR, 271240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, u.python.module), 272240Sigor@sysoev.ru }, 273510Salexander.borisov@nginx.com }; 274240Sigor@sysoev.ru 275510Salexander.borisov@nginx.com 276546Smax.romanov@nginx.com static nxt_conf_map_t nxt_php_app_conf[] = { 277240Sigor@sysoev.ru { 278240Sigor@sysoev.ru nxt_string("root"), 279462Smax.romanov@nginx.com NXT_CONF_MAP_CSTRZ, 280240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, u.php.root), 281240Sigor@sysoev.ru }, 282240Sigor@sysoev.ru 283240Sigor@sysoev.ru { 284240Sigor@sysoev.ru nxt_string("script"), 285240Sigor@sysoev.ru NXT_CONF_MAP_STR, 286240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, u.php.script), 287240Sigor@sysoev.ru }, 288240Sigor@sysoev.ru 289240Sigor@sysoev.ru { 290240Sigor@sysoev.ru nxt_string("index"), 291240Sigor@sysoev.ru NXT_CONF_MAP_STR, 292240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, u.php.index), 293240Sigor@sysoev.ru }, 294687Svbart@nginx.com 295687Svbart@nginx.com { 296687Svbart@nginx.com nxt_string("options"), 297687Svbart@nginx.com NXT_CONF_MAP_PTR, 298687Svbart@nginx.com offsetof(nxt_common_app_conf_t, u.php.options), 299687Svbart@nginx.com }, 300510Salexander.borisov@nginx.com }; 301240Sigor@sysoev.ru 302510Salexander.borisov@nginx.com 303546Smax.romanov@nginx.com static nxt_conf_map_t nxt_perl_app_conf[] = { 304510Salexander.borisov@nginx.com { 305510Salexander.borisov@nginx.com nxt_string("script"), 306510Salexander.borisov@nginx.com NXT_CONF_MAP_CSTRZ, 307510Salexander.borisov@nginx.com offsetof(nxt_common_app_conf_t, u.perl.script), 308510Salexander.borisov@nginx.com }, 309510Salexander.borisov@nginx.com }; 310510Salexander.borisov@nginx.com 311510Salexander.borisov@nginx.com 312584Salexander.borisov@nginx.com static nxt_conf_map_t nxt_ruby_app_conf[] = { 313584Salexander.borisov@nginx.com { 314584Salexander.borisov@nginx.com nxt_string("script"), 315584Salexander.borisov@nginx.com NXT_CONF_MAP_STR, 316584Salexander.borisov@nginx.com offsetof(nxt_common_app_conf_t, u.ruby.script), 317584Salexander.borisov@nginx.com }, 318584Salexander.borisov@nginx.com }; 319584Salexander.borisov@nginx.com 320584Salexander.borisov@nginx.com 321977Smax.romanov@gmail.com static nxt_conf_map_t nxt_java_app_conf[] = { 322977Smax.romanov@gmail.com { 323977Smax.romanov@gmail.com nxt_string("classpath"), 324977Smax.romanov@gmail.com NXT_CONF_MAP_PTR, 325977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.classpath), 326977Smax.romanov@gmail.com }, 327977Smax.romanov@gmail.com { 328977Smax.romanov@gmail.com nxt_string("webapp"), 329977Smax.romanov@gmail.com NXT_CONF_MAP_CSTRZ, 330977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.webapp), 331977Smax.romanov@gmail.com }, 332977Smax.romanov@gmail.com { 333977Smax.romanov@gmail.com nxt_string("options"), 334977Smax.romanov@gmail.com NXT_CONF_MAP_PTR, 335977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.options), 336977Smax.romanov@gmail.com }, 337977Smax.romanov@gmail.com { 338977Smax.romanov@gmail.com nxt_string("unit_jars"), 339977Smax.romanov@gmail.com NXT_CONF_MAP_CSTRZ, 340977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.unit_jars), 341977Smax.romanov@gmail.com }, 342977Smax.romanov@gmail.com 343977Smax.romanov@gmail.com }; 344977Smax.romanov@gmail.com 345977Smax.romanov@gmail.com 346546Smax.romanov@nginx.com static nxt_conf_app_map_t nxt_app_maps[] = { 347804Svbart@nginx.com { nxt_nitems(nxt_external_app_conf), nxt_external_app_conf }, 348804Svbart@nginx.com { nxt_nitems(nxt_python_app_conf), nxt_python_app_conf }, 349804Svbart@nginx.com { nxt_nitems(nxt_php_app_conf), nxt_php_app_conf }, 350804Svbart@nginx.com { nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf }, 351804Svbart@nginx.com { nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf }, 352977Smax.romanov@gmail.com { nxt_nitems(nxt_java_app_conf), nxt_java_app_conf }, 353510Salexander.borisov@nginx.com }; 354510Salexander.borisov@nginx.com 355510Salexander.borisov@nginx.com 356240Sigor@sysoev.ru static void 357240Sigor@sysoev.ru nxt_port_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 358240Sigor@sysoev.ru { 359240Sigor@sysoev.ru nxt_debug(task, "main data: %*s", 360240Sigor@sysoev.ru nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos); 361240Sigor@sysoev.ru } 362240Sigor@sysoev.ru 363240Sigor@sysoev.ru 364240Sigor@sysoev.ru static void 365240Sigor@sysoev.ru nxt_port_main_start_worker_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 366240Sigor@sysoev.ru { 367536Svbart@nginx.com u_char *start, ch; 368536Svbart@nginx.com size_t type_len; 369240Sigor@sysoev.ru nxt_mp_t *mp; 370536Svbart@nginx.com nxt_int_t ret; 371240Sigor@sysoev.ru nxt_buf_t *b; 372318Smax.romanov@nginx.com nxt_port_t *port; 3731182St.nateldemoura@f5.com nxt_runtime_t *rt; 374536Svbart@nginx.com nxt_app_type_t idx; 375240Sigor@sysoev.ru nxt_conf_value_t *conf; 376240Sigor@sysoev.ru nxt_common_app_conf_t app_conf; 377240Sigor@sysoev.ru 378318Smax.romanov@nginx.com ret = NXT_ERROR; 379318Smax.romanov@nginx.com 380352Smax.romanov@nginx.com mp = nxt_mp_create(1024, 128, 256, 32); 381352Smax.romanov@nginx.com 382352Smax.romanov@nginx.com if (nxt_slow_path(mp == NULL)) { 383352Smax.romanov@nginx.com return; 384352Smax.romanov@nginx.com } 385352Smax.romanov@nginx.com 386352Smax.romanov@nginx.com b = nxt_buf_chk_make_plain(mp, msg->buf, msg->size); 387352Smax.romanov@nginx.com 388352Smax.romanov@nginx.com if (b == NULL) { 389352Smax.romanov@nginx.com return; 390352Smax.romanov@nginx.com } 391240Sigor@sysoev.ru 392240Sigor@sysoev.ru nxt_debug(task, "main start worker: %*s", b->mem.free - b->mem.pos, 393240Sigor@sysoev.ru b->mem.pos); 394240Sigor@sysoev.ru 395240Sigor@sysoev.ru nxt_memzero(&app_conf, sizeof(nxt_common_app_conf_t)); 396240Sigor@sysoev.ru 397240Sigor@sysoev.ru start = b->mem.pos; 398240Sigor@sysoev.ru 399240Sigor@sysoev.ru app_conf.name.start = start; 400240Sigor@sysoev.ru app_conf.name.length = nxt_strlen(start); 401*1320Smax.romanov@nginx.com app_conf.shm_limit = 100 * 1024 * 1024; 402240Sigor@sysoev.ru 403240Sigor@sysoev.ru start += app_conf.name.length + 1; 404240Sigor@sysoev.ru 405240Sigor@sysoev.ru conf = nxt_conf_json_parse(mp, start, b->mem.free, NULL); 406240Sigor@sysoev.ru 407240Sigor@sysoev.ru if (conf == NULL) { 408564Svbart@nginx.com nxt_alert(task, "router app configuration parsing error"); 409318Smax.romanov@nginx.com 410318Smax.romanov@nginx.com goto failed; 411240Sigor@sysoev.ru } 412240Sigor@sysoev.ru 4131182St.nateldemoura@f5.com rt = task->thread->runtime; 4141182St.nateldemoura@f5.com 4151182St.nateldemoura@f5.com app_conf.user.start = (u_char*)rt->user_cred.user; 4161182St.nateldemoura@f5.com app_conf.user.length = nxt_strlen(rt->user_cred.user); 417240Sigor@sysoev.ru 418240Sigor@sysoev.ru ret = nxt_conf_map_object(mp, conf, nxt_common_app_conf, 419240Sigor@sysoev.ru nxt_nitems(nxt_common_app_conf), &app_conf); 420240Sigor@sysoev.ru if (ret != NXT_OK) { 421564Svbart@nginx.com nxt_alert(task, "failed to map common app conf received from router"); 422318Smax.romanov@nginx.com goto failed; 423240Sigor@sysoev.ru } 424240Sigor@sysoev.ru 425536Svbart@nginx.com for (type_len = 0; type_len != app_conf.type.length; type_len++) { 426536Svbart@nginx.com ch = app_conf.type.start[type_len]; 427536Svbart@nginx.com 428536Svbart@nginx.com if (ch == ' ' || nxt_isdigit(ch)) { 429536Svbart@nginx.com break; 430536Svbart@nginx.com } 431536Svbart@nginx.com } 432536Svbart@nginx.com 433536Svbart@nginx.com idx = nxt_app_parse_type(app_conf.type.start, type_len); 434510Salexander.borisov@nginx.com 435546Smax.romanov@nginx.com if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) { 436564Svbart@nginx.com nxt_alert(task, "invalid app type %d received from router", (int) idx); 437546Smax.romanov@nginx.com goto failed; 438546Smax.romanov@nginx.com } 439510Salexander.borisov@nginx.com 440546Smax.romanov@nginx.com ret = nxt_conf_map_object(mp, conf, nxt_app_maps[idx].map, 441546Smax.romanov@nginx.com nxt_app_maps[idx].size, &app_conf); 442510Salexander.borisov@nginx.com 443546Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 444564Svbart@nginx.com nxt_alert(task, "failed to map app conf received from router"); 445546Smax.romanov@nginx.com goto failed; 446546Smax.romanov@nginx.com } 447510Salexander.borisov@nginx.com 448*1320Smax.romanov@nginx.com if (app_conf.limits != NULL) { 449*1320Smax.romanov@nginx.com ret = nxt_conf_map_object(mp, app_conf.limits, 450*1320Smax.romanov@nginx.com nxt_common_app_limits_conf, 451*1320Smax.romanov@nginx.com nxt_nitems(nxt_common_app_limits_conf), 452*1320Smax.romanov@nginx.com &app_conf); 453*1320Smax.romanov@nginx.com 454*1320Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 455*1320Smax.romanov@nginx.com nxt_alert(task, "failed to map app limits received from router"); 456*1320Smax.romanov@nginx.com goto failed; 457*1320Smax.romanov@nginx.com } 458*1320Smax.romanov@nginx.com } 459*1320Smax.romanov@nginx.com 460240Sigor@sysoev.ru ret = nxt_main_start_worker_process(task, task->thread->runtime, 461240Sigor@sysoev.ru &app_conf, msg->port_msg.stream); 462240Sigor@sysoev.ru 463318Smax.romanov@nginx.com failed: 464318Smax.romanov@nginx.com 465318Smax.romanov@nginx.com if (ret == NXT_ERROR) { 466318Smax.romanov@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 467318Smax.romanov@nginx.com msg->port_msg.reply_port); 468318Smax.romanov@nginx.com if (nxt_fast_path(port != NULL)) { 469318Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, 470318Smax.romanov@nginx.com -1, msg->port_msg.stream, 0, NULL); 471318Smax.romanov@nginx.com } 472318Smax.romanov@nginx.com } 473318Smax.romanov@nginx.com 474240Sigor@sysoev.ru nxt_mp_destroy(mp); 475240Sigor@sysoev.ru } 476240Sigor@sysoev.ru 477240Sigor@sysoev.ru 478320Smax.romanov@nginx.com static nxt_port_handlers_t nxt_main_process_port_handlers = { 479320Smax.romanov@nginx.com .data = nxt_port_main_data_handler, 480320Smax.romanov@nginx.com .process_ready = nxt_port_process_ready_handler, 481320Smax.romanov@nginx.com .start_worker = nxt_port_main_start_worker_handler, 482320Smax.romanov@nginx.com .socket = nxt_main_port_socket_handler, 483320Smax.romanov@nginx.com .modules = nxt_main_port_modules_handler, 484320Smax.romanov@nginx.com .conf_store = nxt_main_port_conf_store_handler, 485774Svbart@nginx.com #if (NXT_TLS) 486774Svbart@nginx.com .cert_get = nxt_cert_store_get_handler, 487774Svbart@nginx.com .cert_delete = nxt_cert_store_delete_handler, 488774Svbart@nginx.com #endif 489630Svbart@nginx.com .access_log = nxt_main_port_access_log_handler, 490320Smax.romanov@nginx.com .rpc_ready = nxt_port_rpc_handler, 491320Smax.romanov@nginx.com .rpc_error = nxt_port_rpc_handler, 492240Sigor@sysoev.ru }; 493240Sigor@sysoev.ru 494240Sigor@sysoev.ru 495240Sigor@sysoev.ru static nxt_int_t 496240Sigor@sysoev.ru nxt_main_process_port_create(nxt_task_t *task, nxt_runtime_t *rt) 497240Sigor@sysoev.ru { 498240Sigor@sysoev.ru nxt_int_t ret; 499240Sigor@sysoev.ru nxt_port_t *port; 500240Sigor@sysoev.ru nxt_process_t *process; 501240Sigor@sysoev.ru 5021254Shongzhidao@gmail.com port = nxt_runtime_process_port_create(task, rt, nxt_pid, 0, 5031254Shongzhidao@gmail.com NXT_PROCESS_MAIN); 504240Sigor@sysoev.ru if (nxt_slow_path(port == NULL)) { 505240Sigor@sysoev.ru return NXT_ERROR; 506240Sigor@sysoev.ru } 507240Sigor@sysoev.ru 5081254Shongzhidao@gmail.com process = port->process; 509349Smax.romanov@nginx.com 510240Sigor@sysoev.ru ret = nxt_port_socket_init(task, port, 0); 511240Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 512240Sigor@sysoev.ru return ret; 513240Sigor@sysoev.ru } 514240Sigor@sysoev.ru 515240Sigor@sysoev.ru /* 516240Sigor@sysoev.ru * A main process port. A write port is not closed 517240Sigor@sysoev.ru * since it should be inherited by worker processes. 518240Sigor@sysoev.ru */ 519320Smax.romanov@nginx.com nxt_port_enable(task, port, &nxt_main_process_port_handlers); 520240Sigor@sysoev.ru 521240Sigor@sysoev.ru process->ready = 1; 522240Sigor@sysoev.ru 523240Sigor@sysoev.ru return NXT_OK; 524240Sigor@sysoev.ru } 525240Sigor@sysoev.ru 526240Sigor@sysoev.ru 527240Sigor@sysoev.ru static void 528240Sigor@sysoev.ru nxt_main_process_title(nxt_task_t *task) 529240Sigor@sysoev.ru { 530240Sigor@sysoev.ru u_char *p, *end; 531240Sigor@sysoev.ru nxt_uint_t i; 532240Sigor@sysoev.ru u_char title[2048]; 533240Sigor@sysoev.ru 534240Sigor@sysoev.ru end = title + sizeof(title) - 1; 535240Sigor@sysoev.ru 536680Sigor@sysoev.ru p = nxt_sprintf(title, end, "unit: main v" NXT_VERSION " [%s", 537680Sigor@sysoev.ru nxt_process_argv[0]); 538240Sigor@sysoev.ru 539240Sigor@sysoev.ru for (i = 1; nxt_process_argv[i] != NULL; i++) { 540240Sigor@sysoev.ru p = nxt_sprintf(p, end, " %s", nxt_process_argv[i]); 541240Sigor@sysoev.ru } 542240Sigor@sysoev.ru 543240Sigor@sysoev.ru if (p < end) { 544240Sigor@sysoev.ru *p++ = ']'; 545240Sigor@sysoev.ru } 546240Sigor@sysoev.ru 547240Sigor@sysoev.ru *p = '\0'; 548240Sigor@sysoev.ru 549240Sigor@sysoev.ru nxt_process_title(task, "%s", title); 550240Sigor@sysoev.ru } 551240Sigor@sysoev.ru 552240Sigor@sysoev.ru 553240Sigor@sysoev.ru static nxt_int_t 554240Sigor@sysoev.ru nxt_main_start_controller_process(nxt_task_t *task, nxt_runtime_t *rt) 555240Sigor@sysoev.ru { 556240Sigor@sysoev.ru nxt_process_init_t *init; 557240Sigor@sysoev.ru 5581302St.nateldemoura@f5.com static const nxt_str_t name = nxt_string("controller"); 5591302St.nateldemoura@f5.com 5601302St.nateldemoura@f5.com init = nxt_process_init_create(task, NXT_PROCESS_CONTROLLER, &name); 561368Svbart@nginx.com if (nxt_slow_path(init == NULL)) { 562368Svbart@nginx.com return NXT_ERROR; 563368Svbart@nginx.com } 564368Svbart@nginx.com 565368Svbart@nginx.com return nxt_main_create_controller_process(task, rt, init);; 566368Svbart@nginx.com } 567368Svbart@nginx.com 568368Svbart@nginx.com 569368Svbart@nginx.com static nxt_int_t 570368Svbart@nginx.com nxt_main_create_controller_process(nxt_task_t *task, nxt_runtime_t *rt, 571368Svbart@nginx.com nxt_process_init_t *init) 572368Svbart@nginx.com { 573774Svbart@nginx.com ssize_t n; 574774Svbart@nginx.com nxt_int_t ret; 575774Svbart@nginx.com nxt_str_t *conf; 576774Svbart@nginx.com nxt_file_t file; 577774Svbart@nginx.com nxt_file_info_t fi; 578774Svbart@nginx.com nxt_controller_init_t ctrl_init; 579368Svbart@nginx.com 580774Svbart@nginx.com nxt_memzero(&ctrl_init, sizeof(nxt_controller_init_t)); 581774Svbart@nginx.com 582774Svbart@nginx.com conf = &ctrl_init.conf; 583314Svbart@nginx.com 584314Svbart@nginx.com nxt_memzero(&file, sizeof(nxt_file_t)); 585314Svbart@nginx.com 586314Svbart@nginx.com file.name = (nxt_file_name_t *) rt->conf; 587314Svbart@nginx.com 588329Sigor@sysoev.ru ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0); 589314Svbart@nginx.com 590329Sigor@sysoev.ru if (ret == NXT_OK) { 591329Sigor@sysoev.ru ret = nxt_file_info(&file, &fi); 592329Sigor@sysoev.ru 593329Sigor@sysoev.ru if (nxt_fast_path(ret == NXT_OK && nxt_is_file(&fi))) { 594774Svbart@nginx.com conf->length = nxt_file_size(&fi); 595774Svbart@nginx.com conf->start = nxt_malloc(conf->length); 596314Svbart@nginx.com 597774Svbart@nginx.com if (nxt_slow_path(conf->start == NULL)) { 598314Svbart@nginx.com nxt_file_close(task, &file); 599314Svbart@nginx.com return NXT_ERROR; 600314Svbart@nginx.com } 601314Svbart@nginx.com 602774Svbart@nginx.com n = nxt_file_read(&file, conf->start, conf->length, 0); 603314Svbart@nginx.com 604774Svbart@nginx.com if (nxt_slow_path(n != (ssize_t) conf->length)) { 605774Svbart@nginx.com nxt_free(conf->start); 606774Svbart@nginx.com conf->start = NULL; 607314Svbart@nginx.com 608564Svbart@nginx.com nxt_alert(task, "failed to restore previous configuration: " 609564Svbart@nginx.com "cannot read the file"); 610314Svbart@nginx.com } 611314Svbart@nginx.com } 612314Svbart@nginx.com 613314Svbart@nginx.com nxt_file_close(task, &file); 614314Svbart@nginx.com } 615314Svbart@nginx.com 616774Svbart@nginx.com #if (NXT_TLS) 617774Svbart@nginx.com ctrl_init.certs = nxt_cert_store_load(task); 618774Svbart@nginx.com #endif 619774Svbart@nginx.com 620774Svbart@nginx.com init->data = &ctrl_init; 621240Sigor@sysoev.ru 622314Svbart@nginx.com ret = nxt_main_create_worker_process(task, rt, init); 623314Svbart@nginx.com 624774Svbart@nginx.com if (ret == NXT_OK) { 625774Svbart@nginx.com if (conf->start != NULL) { 626774Svbart@nginx.com nxt_free(conf->start); 627774Svbart@nginx.com } 628774Svbart@nginx.com 629774Svbart@nginx.com #if (NXT_TLS) 630774Svbart@nginx.com if (ctrl_init.certs != NULL) { 631774Svbart@nginx.com nxt_cert_store_release(ctrl_init.certs); 632774Svbart@nginx.com } 633774Svbart@nginx.com #endif 634314Svbart@nginx.com } 635314Svbart@nginx.com 636314Svbart@nginx.com return ret; 637240Sigor@sysoev.ru } 638240Sigor@sysoev.ru 639240Sigor@sysoev.ru 640240Sigor@sysoev.ru static nxt_int_t 641240Sigor@sysoev.ru nxt_main_start_discovery_process(nxt_task_t *task, nxt_runtime_t *rt) 642240Sigor@sysoev.ru { 643240Sigor@sysoev.ru nxt_process_init_t *init; 644240Sigor@sysoev.ru 6451302St.nateldemoura@f5.com static const nxt_str_t name = nxt_string("discovery"); 6461302St.nateldemoura@f5.com 6471302St.nateldemoura@f5.com init = nxt_process_init_create(task, NXT_PROCESS_DISCOVERY, &name); 648240Sigor@sysoev.ru if (nxt_slow_path(init == NULL)) { 649240Sigor@sysoev.ru return NXT_ERROR; 650240Sigor@sysoev.ru } 651240Sigor@sysoev.ru 652240Sigor@sysoev.ru return nxt_main_create_worker_process(task, rt, init); 653240Sigor@sysoev.ru } 654240Sigor@sysoev.ru 655240Sigor@sysoev.ru 656240Sigor@sysoev.ru static nxt_int_t 657240Sigor@sysoev.ru nxt_main_start_router_process(nxt_task_t *task, nxt_runtime_t *rt) 658240Sigor@sysoev.ru { 659240Sigor@sysoev.ru nxt_process_init_t *init; 660240Sigor@sysoev.ru 6611302St.nateldemoura@f5.com static const nxt_str_t name = nxt_string("router"); 6621302St.nateldemoura@f5.com 6631302St.nateldemoura@f5.com init = nxt_process_init_create(task, NXT_PROCESS_ROUTER, &name); 664240Sigor@sysoev.ru if (nxt_slow_path(init == NULL)) { 665240Sigor@sysoev.ru return NXT_ERROR; 666240Sigor@sysoev.ru } 667240Sigor@sysoev.ru 6681302St.nateldemoura@f5.com return nxt_main_create_router_process(task, rt, init); 6691302St.nateldemoura@f5.com } 6701302St.nateldemoura@f5.com 6711302St.nateldemoura@f5.com 6721302St.nateldemoura@f5.com static nxt_int_t 6731302St.nateldemoura@f5.com nxt_main_create_router_process(nxt_task_t *task, nxt_runtime_t *rt, 6741302St.nateldemoura@f5.com nxt_process_init_t *init) 6751302St.nateldemoura@f5.com { 6761302St.nateldemoura@f5.com nxt_main_stop_worker_processes(task, rt); 677240Sigor@sysoev.ru 678240Sigor@sysoev.ru return nxt_main_create_worker_process(task, rt, init); 679240Sigor@sysoev.ru } 680240Sigor@sysoev.ru 6811302St.nateldemoura@f5.com 682240Sigor@sysoev.ru static nxt_int_t 683240Sigor@sysoev.ru nxt_main_start_worker_process(nxt_task_t *task, nxt_runtime_t *rt, 684240Sigor@sysoev.ru nxt_common_app_conf_t *app_conf, uint32_t stream) 685240Sigor@sysoev.ru { 6861306St.nateldemoura@f5.com nxt_int_t cap_setid; 6871182St.nateldemoura@f5.com nxt_int_t ret; 688240Sigor@sysoev.ru nxt_process_init_t *init; 689240Sigor@sysoev.ru 6901302St.nateldemoura@f5.com init = nxt_process_init_create(task, NXT_PROCESS_WORKER, &app_conf->name); 691240Sigor@sysoev.ru if (nxt_slow_path(init == NULL)) { 692240Sigor@sysoev.ru return NXT_ERROR; 693240Sigor@sysoev.ru } 694240Sigor@sysoev.ru 6951306St.nateldemoura@f5.com cap_setid = rt->capabilities.setid; 6961306St.nateldemoura@f5.com 6971306St.nateldemoura@f5.com if (app_conf->isolation != NULL) { 6981306St.nateldemoura@f5.com ret = nxt_init_isolation(task, app_conf->isolation, init); 6991306St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 7001306St.nateldemoura@f5.com goto fail; 7011306St.nateldemoura@f5.com } 7021306St.nateldemoura@f5.com } 7031306St.nateldemoura@f5.com 7041306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 7051306St.nateldemoura@f5.com if (NXT_CLONE_USER(init->isolation.clone.flags)) { 7061306St.nateldemoura@f5.com cap_setid = 1; 7071306St.nateldemoura@f5.com } 7081306St.nateldemoura@f5.com #endif 7091306St.nateldemoura@f5.com 7101306St.nateldemoura@f5.com if (cap_setid) { 7111302St.nateldemoura@f5.com ret = nxt_process_init_creds_set(task, init, &app_conf->user, 7121302St.nateldemoura@f5.com &app_conf->group); 7131302St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 7141202St.nateldemoura@f5.com goto fail; 7151182St.nateldemoura@f5.com } 7161182St.nateldemoura@f5.com 717240Sigor@sysoev.ru } else { 7181182St.nateldemoura@f5.com if (!nxt_str_eq(&app_conf->user, (u_char *) rt->user_cred.user, 7191182St.nateldemoura@f5.com nxt_strlen(rt->user_cred.user))) 7201182St.nateldemoura@f5.com { 7211182St.nateldemoura@f5.com nxt_alert(task, "cannot set user \"%V\" for app \"%V\": " 7221182St.nateldemoura@f5.com "missing capabilities", &app_conf->user, &app_conf->name); 7231202St.nateldemoura@f5.com goto fail; 7241182St.nateldemoura@f5.com } 725240Sigor@sysoev.ru 7261182St.nateldemoura@f5.com if (app_conf->group.length > 0 7271182St.nateldemoura@f5.com && !nxt_str_eq(&app_conf->group, (u_char *) rt->group, 7281182St.nateldemoura@f5.com nxt_strlen(rt->group))) 7291182St.nateldemoura@f5.com { 7301182St.nateldemoura@f5.com nxt_alert(task, "cannot set group \"%V\" for app \"%V\": " 7311182St.nateldemoura@f5.com "missing capabilities", &app_conf->group, 7321182St.nateldemoura@f5.com &app_conf->name); 7331202St.nateldemoura@f5.com goto fail; 7341182St.nateldemoura@f5.com } 735240Sigor@sysoev.ru } 736240Sigor@sysoev.ru 737240Sigor@sysoev.ru init->data = app_conf; 738240Sigor@sysoev.ru init->stream = stream; 739240Sigor@sysoev.ru 7401306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 7411306St.nateldemoura@f5.com ret = nxt_init_vldt_isolation_creds(task, init); 7421182St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 7431202St.nateldemoura@f5.com goto fail; 7441182St.nateldemoura@f5.com } 7451306St.nateldemoura@f5.com #endif 7461182St.nateldemoura@f5.com 747240Sigor@sysoev.ru return nxt_main_create_worker_process(task, rt, init); 7481202St.nateldemoura@f5.com 7491202St.nateldemoura@f5.com fail: 7501202St.nateldemoura@f5.com 7511302St.nateldemoura@f5.com nxt_mp_destroy(init->mem_pool); 7521202St.nateldemoura@f5.com 7531202St.nateldemoura@f5.com return NXT_ERROR; 754240Sigor@sysoev.ru } 755240Sigor@sysoev.ru 756240Sigor@sysoev.ru 7571302St.nateldemoura@f5.com nxt_int_t 758240Sigor@sysoev.ru nxt_main_create_worker_process(nxt_task_t *task, nxt_runtime_t *rt, 759240Sigor@sysoev.ru nxt_process_init_t *init) 760240Sigor@sysoev.ru { 761240Sigor@sysoev.ru nxt_int_t ret; 762240Sigor@sysoev.ru nxt_pid_t pid; 763240Sigor@sysoev.ru nxt_port_t *port; 764240Sigor@sysoev.ru nxt_process_t *process; 765240Sigor@sysoev.ru 766240Sigor@sysoev.ru /* 767240Sigor@sysoev.ru * TODO: remove process, init, ports from array on memory and fork failures. 768240Sigor@sysoev.ru */ 769240Sigor@sysoev.ru 770240Sigor@sysoev.ru process = nxt_runtime_process_new(rt); 771240Sigor@sysoev.ru if (nxt_slow_path(process == NULL)) { 7721302St.nateldemoura@f5.com nxt_mp_destroy(init->mem_pool); 7731253Smax.romanov@nginx.com 774240Sigor@sysoev.ru return NXT_ERROR; 775240Sigor@sysoev.ru } 776240Sigor@sysoev.ru 777240Sigor@sysoev.ru process->init = init; 778240Sigor@sysoev.ru 779240Sigor@sysoev.ru port = nxt_port_new(task, 0, 0, init->type); 780240Sigor@sysoev.ru if (nxt_slow_path(port == NULL)) { 781349Smax.romanov@nginx.com nxt_process_use(task, process, -1); 782240Sigor@sysoev.ru return NXT_ERROR; 783240Sigor@sysoev.ru } 784240Sigor@sysoev.ru 785240Sigor@sysoev.ru nxt_process_port_add(task, process, port); 786240Sigor@sysoev.ru 787349Smax.romanov@nginx.com nxt_process_use(task, process, -1); 788349Smax.romanov@nginx.com 789240Sigor@sysoev.ru ret = nxt_port_socket_init(task, port, 0); 790240Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 791343Smax.romanov@nginx.com nxt_port_use(task, port, -1); 792240Sigor@sysoev.ru return ret; 793240Sigor@sysoev.ru } 794240Sigor@sysoev.ru 795240Sigor@sysoev.ru pid = nxt_process_create(task, process); 796240Sigor@sysoev.ru 797240Sigor@sysoev.ru switch (pid) { 798240Sigor@sysoev.ru 799240Sigor@sysoev.ru case -1: 8001180Smax.romanov@nginx.com nxt_port_close(task, port); 8011180Smax.romanov@nginx.com nxt_port_use(task, port, -1); 8021180Smax.romanov@nginx.com 803240Sigor@sysoev.ru return NXT_ERROR; 804240Sigor@sysoev.ru 805240Sigor@sysoev.ru case 0: 806240Sigor@sysoev.ru /* A worker process, return to the event engine work queue loop. */ 8071180Smax.romanov@nginx.com nxt_port_use(task, port, -1); 8081180Smax.romanov@nginx.com 809240Sigor@sysoev.ru return NXT_AGAIN; 810240Sigor@sysoev.ru 811240Sigor@sysoev.ru default: 812240Sigor@sysoev.ru /* The main process created a new process. */ 813240Sigor@sysoev.ru 814240Sigor@sysoev.ru nxt_port_read_close(port); 815240Sigor@sysoev.ru nxt_port_write_enable(task, port); 816240Sigor@sysoev.ru 8171180Smax.romanov@nginx.com nxt_port_use(task, port, -1); 8181180Smax.romanov@nginx.com 819240Sigor@sysoev.ru return NXT_OK; 820240Sigor@sysoev.ru } 821240Sigor@sysoev.ru } 822240Sigor@sysoev.ru 823240Sigor@sysoev.ru 824240Sigor@sysoev.ru void 825754Smax.romanov@nginx.com nxt_main_stop_all_processes(nxt_task_t *task, nxt_runtime_t *rt) 826240Sigor@sysoev.ru { 827240Sigor@sysoev.ru nxt_port_t *port; 828240Sigor@sysoev.ru nxt_process_t *process; 829240Sigor@sysoev.ru 830277Sigor@sysoev.ru nxt_runtime_process_each(rt, process) { 831277Sigor@sysoev.ru 832240Sigor@sysoev.ru if (nxt_pid != process->pid) { 833240Sigor@sysoev.ru nxt_process_port_each(process, port) { 834240Sigor@sysoev.ru 835240Sigor@sysoev.ru (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, 836240Sigor@sysoev.ru -1, 0, 0, NULL); 837240Sigor@sysoev.ru 838240Sigor@sysoev.ru } nxt_process_port_loop; 839240Sigor@sysoev.ru } 840277Sigor@sysoev.ru 841277Sigor@sysoev.ru } nxt_runtime_process_loop; 842240Sigor@sysoev.ru } 843240Sigor@sysoev.ru 844240Sigor@sysoev.ru 845240Sigor@sysoev.ru 846240Sigor@sysoev.ru static void 847240Sigor@sysoev.ru nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, void *data) 848240Sigor@sysoev.ru { 849240Sigor@sysoev.ru nxt_debug(task, "sigterm handler signo:%d (%s)", 850240Sigor@sysoev.ru (int) (uintptr_t) obj, data); 851240Sigor@sysoev.ru 852240Sigor@sysoev.ru /* TODO: fast exit. */ 853240Sigor@sysoev.ru 854240Sigor@sysoev.ru nxt_exiting = 1; 855240Sigor@sysoev.ru 856697Sigor@sysoev.ru nxt_runtime_quit(task, 0); 857240Sigor@sysoev.ru } 858240Sigor@sysoev.ru 859240Sigor@sysoev.ru 860240Sigor@sysoev.ru static void 861240Sigor@sysoev.ru nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, void *data) 862240Sigor@sysoev.ru { 863240Sigor@sysoev.ru nxt_debug(task, "sigquit handler signo:%d (%s)", 864240Sigor@sysoev.ru (int) (uintptr_t) obj, data); 865240Sigor@sysoev.ru 866240Sigor@sysoev.ru /* TODO: graceful exit. */ 867240Sigor@sysoev.ru 868240Sigor@sysoev.ru nxt_exiting = 1; 869240Sigor@sysoev.ru 870697Sigor@sysoev.ru nxt_runtime_quit(task, 0); 871240Sigor@sysoev.ru } 872240Sigor@sysoev.ru 873240Sigor@sysoev.ru 874240Sigor@sysoev.ru static void 875240Sigor@sysoev.ru nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, void *data) 876240Sigor@sysoev.ru { 877240Sigor@sysoev.ru nxt_mp_t *mp; 878240Sigor@sysoev.ru nxt_int_t ret; 879240Sigor@sysoev.ru nxt_uint_t n; 880631Svbart@nginx.com nxt_port_t *port; 881240Sigor@sysoev.ru nxt_file_t *file, *new_file; 882631Svbart@nginx.com nxt_array_t *new_files; 883240Sigor@sysoev.ru nxt_runtime_t *rt; 884240Sigor@sysoev.ru 885240Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "signal %d (%s) recevied, %s", 886240Sigor@sysoev.ru (int) (uintptr_t) obj, data, "log files rotation"); 887240Sigor@sysoev.ru 888631Svbart@nginx.com rt = task->thread->runtime; 889631Svbart@nginx.com 890631Svbart@nginx.com port = rt->port_by_type[NXT_PROCESS_ROUTER]; 891631Svbart@nginx.com 892631Svbart@nginx.com if (nxt_fast_path(port != NULL)) { 893631Svbart@nginx.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_ACCESS_LOG, 894631Svbart@nginx.com -1, 0, 0, NULL); 895631Svbart@nginx.com } 896631Svbart@nginx.com 897240Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 898240Sigor@sysoev.ru if (mp == NULL) { 899240Sigor@sysoev.ru return; 900240Sigor@sysoev.ru } 901240Sigor@sysoev.ru 902240Sigor@sysoev.ru n = nxt_list_nelts(rt->log_files); 903240Sigor@sysoev.ru 904240Sigor@sysoev.ru new_files = nxt_array_create(mp, n, sizeof(nxt_file_t)); 905240Sigor@sysoev.ru if (new_files == NULL) { 906240Sigor@sysoev.ru nxt_mp_destroy(mp); 907240Sigor@sysoev.ru return; 908240Sigor@sysoev.ru } 909240Sigor@sysoev.ru 910240Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 911240Sigor@sysoev.ru 912240Sigor@sysoev.ru /* This allocation cannot fail. */ 913240Sigor@sysoev.ru new_file = nxt_array_add(new_files); 914240Sigor@sysoev.ru 915240Sigor@sysoev.ru new_file->name = file->name; 916240Sigor@sysoev.ru new_file->fd = NXT_FILE_INVALID; 917564Svbart@nginx.com new_file->log_level = NXT_LOG_ALERT; 918240Sigor@sysoev.ru 919240Sigor@sysoev.ru ret = nxt_file_open(task, new_file, O_WRONLY | O_APPEND, O_CREAT, 920240Sigor@sysoev.ru NXT_FILE_OWNER_ACCESS); 921240Sigor@sysoev.ru 922240Sigor@sysoev.ru if (ret != NXT_OK) { 923240Sigor@sysoev.ru goto fail; 924240Sigor@sysoev.ru } 925240Sigor@sysoev.ru 926240Sigor@sysoev.ru } nxt_list_loop; 927240Sigor@sysoev.ru 928240Sigor@sysoev.ru new_file = new_files->elts; 929240Sigor@sysoev.ru 930240Sigor@sysoev.ru ret = nxt_file_stderr(&new_file[0]); 931240Sigor@sysoev.ru 932240Sigor@sysoev.ru if (ret == NXT_OK) { 933240Sigor@sysoev.ru n = 0; 934240Sigor@sysoev.ru 935240Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 936240Sigor@sysoev.ru 937240Sigor@sysoev.ru nxt_port_change_log_file(task, rt, n, new_file[n].fd); 938240Sigor@sysoev.ru /* 939240Sigor@sysoev.ru * The old log file descriptor must be closed at the moment 940240Sigor@sysoev.ru * when no other threads use it. dup2() allows to use the 941240Sigor@sysoev.ru * old file descriptor for new log file. This change is 942240Sigor@sysoev.ru * performed atomically in the kernel. 943240Sigor@sysoev.ru */ 944240Sigor@sysoev.ru (void) nxt_file_redirect(file, new_file[n].fd); 945240Sigor@sysoev.ru 946240Sigor@sysoev.ru n++; 947240Sigor@sysoev.ru 948240Sigor@sysoev.ru } nxt_list_loop; 949240Sigor@sysoev.ru 950240Sigor@sysoev.ru nxt_mp_destroy(mp); 951240Sigor@sysoev.ru return; 9521008Szelenkov@nginx.com } 953240Sigor@sysoev.ru 954240Sigor@sysoev.ru fail: 955240Sigor@sysoev.ru 956240Sigor@sysoev.ru new_file = new_files->elts; 957240Sigor@sysoev.ru n = new_files->nelts; 958240Sigor@sysoev.ru 959240Sigor@sysoev.ru while (n != 0) { 960240Sigor@sysoev.ru if (new_file->fd != NXT_FILE_INVALID) { 961240Sigor@sysoev.ru nxt_file_close(task, new_file); 962240Sigor@sysoev.ru } 963240Sigor@sysoev.ru 964240Sigor@sysoev.ru new_file++; 965240Sigor@sysoev.ru n--; 966240Sigor@sysoev.ru } 967240Sigor@sysoev.ru 968240Sigor@sysoev.ru nxt_mp_destroy(mp); 969240Sigor@sysoev.ru } 970240Sigor@sysoev.ru 971240Sigor@sysoev.ru 972240Sigor@sysoev.ru static void 973240Sigor@sysoev.ru nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, void *data) 974240Sigor@sysoev.ru { 975240Sigor@sysoev.ru int status; 976240Sigor@sysoev.ru nxt_err_t err; 977240Sigor@sysoev.ru nxt_pid_t pid; 978240Sigor@sysoev.ru 979240Sigor@sysoev.ru nxt_debug(task, "sigchld handler signo:%d (%s)", 980240Sigor@sysoev.ru (int) (uintptr_t) obj, data); 981240Sigor@sysoev.ru 982240Sigor@sysoev.ru for ( ;; ) { 983240Sigor@sysoev.ru pid = waitpid(-1, &status, WNOHANG); 984240Sigor@sysoev.ru 985240Sigor@sysoev.ru if (pid == -1) { 986240Sigor@sysoev.ru 987240Sigor@sysoev.ru switch (err = nxt_errno) { 988240Sigor@sysoev.ru 989240Sigor@sysoev.ru case NXT_ECHILD: 990240Sigor@sysoev.ru return; 991240Sigor@sysoev.ru 992240Sigor@sysoev.ru case NXT_EINTR: 993240Sigor@sysoev.ru continue; 994240Sigor@sysoev.ru 995240Sigor@sysoev.ru default: 996564Svbart@nginx.com nxt_alert(task, "waitpid() failed: %E", err); 997240Sigor@sysoev.ru return; 998240Sigor@sysoev.ru } 999240Sigor@sysoev.ru } 1000240Sigor@sysoev.ru 1001240Sigor@sysoev.ru nxt_debug(task, "waitpid(): %PI", pid); 1002240Sigor@sysoev.ru 1003240Sigor@sysoev.ru if (pid == 0) { 1004240Sigor@sysoev.ru return; 1005240Sigor@sysoev.ru } 1006240Sigor@sysoev.ru 1007240Sigor@sysoev.ru if (WTERMSIG(status)) { 1008240Sigor@sysoev.ru #ifdef WCOREDUMP 1009564Svbart@nginx.com nxt_alert(task, "process %PI exited on signal %d%s", 1010564Svbart@nginx.com pid, WTERMSIG(status), 1011564Svbart@nginx.com WCOREDUMP(status) ? " (core dumped)" : ""); 1012240Sigor@sysoev.ru #else 1013564Svbart@nginx.com nxt_alert(task, "process %PI exited on signal %d", 1014564Svbart@nginx.com pid, WTERMSIG(status)); 1015240Sigor@sysoev.ru #endif 1016240Sigor@sysoev.ru 1017240Sigor@sysoev.ru } else { 1018240Sigor@sysoev.ru nxt_trace(task, "process %PI exited with code %d", 1019240Sigor@sysoev.ru pid, WEXITSTATUS(status)); 1020240Sigor@sysoev.ru } 1021240Sigor@sysoev.ru 1022240Sigor@sysoev.ru nxt_main_cleanup_worker_process(task, pid); 1023240Sigor@sysoev.ru } 1024240Sigor@sysoev.ru } 1025240Sigor@sysoev.ru 1026240Sigor@sysoev.ru 1027240Sigor@sysoev.ru static void 1028944Sigor@sysoev.ru nxt_main_process_signal_handler(nxt_task_t *task, void *obj, void *data) 1029944Sigor@sysoev.ru { 1030944Sigor@sysoev.ru nxt_trace(task, "signal signo:%d (%s) recevied, ignored", 1031944Sigor@sysoev.ru (int) (uintptr_t) obj, data); 1032944Sigor@sysoev.ru } 1033944Sigor@sysoev.ru 1034944Sigor@sysoev.ru 1035944Sigor@sysoev.ru static void 1036240Sigor@sysoev.ru nxt_main_cleanup_worker_process(nxt_task_t *task, nxt_pid_t pid) 1037240Sigor@sysoev.ru { 10381302St.nateldemoura@f5.com nxt_buf_t *buf; 10391302St.nateldemoura@f5.com nxt_port_t *port; 10401302St.nateldemoura@f5.com nxt_runtime_t *rt; 10411302St.nateldemoura@f5.com nxt_process_t *process; 10421302St.nateldemoura@f5.com nxt_process_type_t ptype; 10431302St.nateldemoura@f5.com nxt_process_init_t *init; 10441302St.nateldemoura@f5.com nxt_process_restart_t restart; 1045240Sigor@sysoev.ru 1046240Sigor@sysoev.ru rt = task->thread->runtime; 1047240Sigor@sysoev.ru 1048240Sigor@sysoev.ru process = nxt_runtime_process_find(rt, pid); 1049240Sigor@sysoev.ru 1050240Sigor@sysoev.ru if (process) { 1051240Sigor@sysoev.ru init = process->init; 10521253Smax.romanov@nginx.com process->init = NULL; 1053240Sigor@sysoev.ru 1054366Smax.romanov@nginx.com ptype = nxt_process_type(process); 10551302St.nateldemoura@f5.com restart = nxt_process_restarts[ptype]; 1056366Smax.romanov@nginx.com 10571253Smax.romanov@nginx.com if (process->ready) { 1058782Smax.romanov@nginx.com init->stream = 0; 1059782Smax.romanov@nginx.com } 1060782Smax.romanov@nginx.com 1061349Smax.romanov@nginx.com nxt_process_close_ports(task, process); 1062240Sigor@sysoev.ru 1063240Sigor@sysoev.ru if (nxt_exiting) { 10641302St.nateldemoura@f5.com nxt_mp_destroy(init->mem_pool); 10651302St.nateldemoura@f5.com 10661211Smax.romanov@nginx.com if (rt->nprocesses <= 2) { 1067697Sigor@sysoev.ru nxt_runtime_quit(task, 0); 1068240Sigor@sysoev.ru } 1069240Sigor@sysoev.ru 10701211Smax.romanov@nginx.com return; 10711211Smax.romanov@nginx.com } 10721211Smax.romanov@nginx.com 10731211Smax.romanov@nginx.com nxt_runtime_process_each(rt, process) { 10741211Smax.romanov@nginx.com 10751211Smax.romanov@nginx.com if (process->pid == nxt_pid 10761211Smax.romanov@nginx.com || process->pid == pid 10771211Smax.romanov@nginx.com || nxt_queue_is_empty(&process->ports)) 10781211Smax.romanov@nginx.com { 10791211Smax.romanov@nginx.com continue; 10801211Smax.romanov@nginx.com } 10811211Smax.romanov@nginx.com 10821211Smax.romanov@nginx.com port = nxt_process_port_first(process); 10831211Smax.romanov@nginx.com 10841211Smax.romanov@nginx.com if (nxt_proc_remove_notify_matrix[ptype][port->type] == 0) { 10851211Smax.romanov@nginx.com continue; 10861211Smax.romanov@nginx.com } 1087754Smax.romanov@nginx.com 10881211Smax.romanov@nginx.com buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 10891211Smax.romanov@nginx.com sizeof(pid)); 10901211Smax.romanov@nginx.com if (nxt_slow_path(buf == NULL)) { 10911211Smax.romanov@nginx.com continue; 10921211Smax.romanov@nginx.com } 10931211Smax.romanov@nginx.com 10941211Smax.romanov@nginx.com buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid)); 1095240Sigor@sysoev.ru 10961211Smax.romanov@nginx.com nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID, 10971211Smax.romanov@nginx.com -1, init->stream, 0, buf); 10981211Smax.romanov@nginx.com } nxt_runtime_process_loop; 10991211Smax.romanov@nginx.com 11001302St.nateldemoura@f5.com if (restart != NULL) { 11011302St.nateldemoura@f5.com restart(task, rt, init); 11021211Smax.romanov@nginx.com 11031211Smax.romanov@nginx.com } else { 11041302St.nateldemoura@f5.com nxt_mp_destroy(init->mem_pool); 1105240Sigor@sysoev.ru } 1106240Sigor@sysoev.ru } 1107240Sigor@sysoev.ru } 1108240Sigor@sysoev.ru 1109240Sigor@sysoev.ru 1110240Sigor@sysoev.ru static void 1111754Smax.romanov@nginx.com nxt_main_stop_worker_processes(nxt_task_t *task, nxt_runtime_t *rt) 1112754Smax.romanov@nginx.com { 1113754Smax.romanov@nginx.com nxt_port_t *port; 1114754Smax.romanov@nginx.com nxt_process_t *process; 1115754Smax.romanov@nginx.com 1116754Smax.romanov@nginx.com nxt_runtime_process_each(rt, process) { 1117754Smax.romanov@nginx.com 1118754Smax.romanov@nginx.com nxt_process_port_each(process, port) { 1119754Smax.romanov@nginx.com 1120754Smax.romanov@nginx.com if (port->type == NXT_PROCESS_WORKER) { 1121754Smax.romanov@nginx.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, 1122754Smax.romanov@nginx.com -1, 0, 0, NULL); 1123754Smax.romanov@nginx.com } 1124754Smax.romanov@nginx.com 1125754Smax.romanov@nginx.com } nxt_process_port_loop; 1126754Smax.romanov@nginx.com 1127754Smax.romanov@nginx.com } nxt_runtime_process_loop; 1128754Smax.romanov@nginx.com } 1129754Smax.romanov@nginx.com 1130754Smax.romanov@nginx.com 1131754Smax.romanov@nginx.com static void 1132240Sigor@sysoev.ru nxt_main_port_socket_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1133240Sigor@sysoev.ru { 1134240Sigor@sysoev.ru size_t size; 1135240Sigor@sysoev.ru nxt_int_t ret; 1136240Sigor@sysoev.ru nxt_buf_t *b, *out; 1137240Sigor@sysoev.ru nxt_port_t *port; 1138240Sigor@sysoev.ru nxt_sockaddr_t *sa; 1139240Sigor@sysoev.ru nxt_port_msg_type_t type; 1140240Sigor@sysoev.ru nxt_listening_socket_t ls; 1141240Sigor@sysoev.ru u_char message[2048]; 1142240Sigor@sysoev.ru 1143240Sigor@sysoev.ru b = msg->buf; 1144240Sigor@sysoev.ru sa = (nxt_sockaddr_t *) b->mem.pos; 1145240Sigor@sysoev.ru 1146352Smax.romanov@nginx.com /* TODO check b size and make plain */ 1147352Smax.romanov@nginx.com 1148240Sigor@sysoev.ru out = NULL; 1149240Sigor@sysoev.ru 1150240Sigor@sysoev.ru ls.socket = -1; 1151240Sigor@sysoev.ru ls.error = NXT_SOCKET_ERROR_SYSTEM; 1152240Sigor@sysoev.ru ls.start = message; 1153240Sigor@sysoev.ru ls.end = message + sizeof(message); 1154240Sigor@sysoev.ru 1155240Sigor@sysoev.ru port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 1156240Sigor@sysoev.ru msg->port_msg.reply_port); 1157240Sigor@sysoev.ru 1158240Sigor@sysoev.ru nxt_debug(task, "listening socket \"%*s\"", 1159493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa)); 1160240Sigor@sysoev.ru 1161240Sigor@sysoev.ru ret = nxt_main_listening_socket(sa, &ls); 1162240Sigor@sysoev.ru 1163240Sigor@sysoev.ru if (ret == NXT_OK) { 1164240Sigor@sysoev.ru nxt_debug(task, "socket(\"%*s\"): %d", 1165493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), ls.socket); 1166240Sigor@sysoev.ru 1167240Sigor@sysoev.ru type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD; 1168240Sigor@sysoev.ru 1169240Sigor@sysoev.ru } else { 1170240Sigor@sysoev.ru size = ls.end - ls.start; 1171240Sigor@sysoev.ru 1172564Svbart@nginx.com nxt_alert(task, "%*s", size, ls.start); 1173240Sigor@sysoev.ru 1174342Smax.romanov@nginx.com out = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 1175342Smax.romanov@nginx.com size + 1); 1176240Sigor@sysoev.ru if (nxt_slow_path(out == NULL)) { 1177240Sigor@sysoev.ru return; 1178240Sigor@sysoev.ru } 1179240Sigor@sysoev.ru 1180240Sigor@sysoev.ru *out->mem.free++ = (uint8_t) ls.error; 1181240Sigor@sysoev.ru 1182240Sigor@sysoev.ru out->mem.free = nxt_cpymem(out->mem.free, ls.start, size); 1183240Sigor@sysoev.ru 1184240Sigor@sysoev.ru type = NXT_PORT_MSG_RPC_ERROR; 1185240Sigor@sysoev.ru } 1186240Sigor@sysoev.ru 1187240Sigor@sysoev.ru nxt_port_socket_write(task, port, type, ls.socket, msg->port_msg.stream, 1188240Sigor@sysoev.ru 0, out); 1189240Sigor@sysoev.ru } 1190240Sigor@sysoev.ru 1191240Sigor@sysoev.ru 1192240Sigor@sysoev.ru static nxt_int_t 1193240Sigor@sysoev.ru nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls) 1194240Sigor@sysoev.ru { 1195240Sigor@sysoev.ru nxt_err_t err; 1196240Sigor@sysoev.ru nxt_socket_t s; 1197240Sigor@sysoev.ru 1198240Sigor@sysoev.ru const socklen_t length = sizeof(int); 1199240Sigor@sysoev.ru static const int enable = 1; 1200240Sigor@sysoev.ru 1201240Sigor@sysoev.ru s = socket(sa->u.sockaddr.sa_family, sa->type, 0); 1202240Sigor@sysoev.ru 1203240Sigor@sysoev.ru if (nxt_slow_path(s == -1)) { 1204240Sigor@sysoev.ru err = nxt_errno; 1205240Sigor@sysoev.ru 1206240Sigor@sysoev.ru #if (NXT_INET6) 1207240Sigor@sysoev.ru 1208240Sigor@sysoev.ru if (err == EAFNOSUPPORT && sa->u.sockaddr.sa_family == AF_INET6) { 1209240Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_NOINET6; 1210240Sigor@sysoev.ru } 1211240Sigor@sysoev.ru 1212240Sigor@sysoev.ru #endif 1213240Sigor@sysoev.ru 1214240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1215240Sigor@sysoev.ru "socket(\\\"%*s\\\") failed %E", 1216493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), err); 1217240Sigor@sysoev.ru 1218240Sigor@sysoev.ru return NXT_ERROR; 1219240Sigor@sysoev.ru } 1220240Sigor@sysoev.ru 1221240Sigor@sysoev.ru if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, length) != 0) { 1222240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1223240Sigor@sysoev.ru "setsockopt(\\\"%*s\\\", SO_REUSEADDR) failed %E", 1224493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), 1225493Spluknet@nginx.com nxt_errno); 1226240Sigor@sysoev.ru goto fail; 1227240Sigor@sysoev.ru } 1228240Sigor@sysoev.ru 1229240Sigor@sysoev.ru #if (NXT_INET6) 1230240Sigor@sysoev.ru 1231240Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_INET6) { 1232240Sigor@sysoev.ru 1233240Sigor@sysoev.ru if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, length) != 0) { 1234240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1235240Sigor@sysoev.ru "setsockopt(\\\"%*s\\\", IPV6_V6ONLY) failed %E", 1236493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), 1237493Spluknet@nginx.com nxt_errno); 1238240Sigor@sysoev.ru goto fail; 1239240Sigor@sysoev.ru } 1240240Sigor@sysoev.ru } 1241240Sigor@sysoev.ru 1242240Sigor@sysoev.ru #endif 1243240Sigor@sysoev.ru 1244240Sigor@sysoev.ru if (bind(s, &sa->u.sockaddr, sa->socklen) != 0) { 1245240Sigor@sysoev.ru err = nxt_errno; 1246240Sigor@sysoev.ru 1247240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 1248240Sigor@sysoev.ru 1249240Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_UNIX) { 1250240Sigor@sysoev.ru switch (err) { 1251240Sigor@sysoev.ru 1252240Sigor@sysoev.ru case EACCES: 1253240Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_ACCESS; 1254240Sigor@sysoev.ru break; 1255240Sigor@sysoev.ru 1256240Sigor@sysoev.ru case ENOENT: 1257240Sigor@sysoev.ru case ENOTDIR: 1258240Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_PATH; 1259240Sigor@sysoev.ru break; 1260240Sigor@sysoev.ru } 1261240Sigor@sysoev.ru 1262908Sigor@sysoev.ru } else 1263908Sigor@sysoev.ru #endif 1264908Sigor@sysoev.ru { 1265908Sigor@sysoev.ru switch (err) { 1266240Sigor@sysoev.ru 1267908Sigor@sysoev.ru case EACCES: 1268908Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_PORT; 1269908Sigor@sysoev.ru break; 1270240Sigor@sysoev.ru 1271908Sigor@sysoev.ru case EADDRINUSE: 1272908Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_INUSE; 1273908Sigor@sysoev.ru break; 1274240Sigor@sysoev.ru 1275908Sigor@sysoev.ru case EADDRNOTAVAIL: 1276908Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_NOADDR; 1277908Sigor@sysoev.ru break; 1278908Sigor@sysoev.ru } 1279240Sigor@sysoev.ru } 1280240Sigor@sysoev.ru 1281240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, "bind(\\\"%*s\\\") failed %E", 1282493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), err); 1283240Sigor@sysoev.ru goto fail; 1284240Sigor@sysoev.ru } 1285240Sigor@sysoev.ru 1286240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 1287240Sigor@sysoev.ru 1288240Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_UNIX) { 1289240Sigor@sysoev.ru char *filename; 1290240Sigor@sysoev.ru mode_t access; 1291240Sigor@sysoev.ru 1292240Sigor@sysoev.ru filename = sa->u.sockaddr_un.sun_path; 1293240Sigor@sysoev.ru access = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 1294240Sigor@sysoev.ru 1295240Sigor@sysoev.ru if (chmod(filename, access) != 0) { 1296240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1297494Spluknet@nginx.com "chmod(\\\"%s\\\") failed %E", 1298240Sigor@sysoev.ru filename, nxt_errno); 1299240Sigor@sysoev.ru goto fail; 1300240Sigor@sysoev.ru } 1301240Sigor@sysoev.ru } 1302240Sigor@sysoev.ru 1303240Sigor@sysoev.ru #endif 1304240Sigor@sysoev.ru 1305240Sigor@sysoev.ru ls->socket = s; 1306240Sigor@sysoev.ru 1307240Sigor@sysoev.ru return NXT_OK; 1308240Sigor@sysoev.ru 1309240Sigor@sysoev.ru fail: 1310240Sigor@sysoev.ru 1311240Sigor@sysoev.ru (void) close(s); 1312240Sigor@sysoev.ru 1313240Sigor@sysoev.ru return NXT_ERROR; 1314240Sigor@sysoev.ru } 1315240Sigor@sysoev.ru 1316240Sigor@sysoev.ru 1317240Sigor@sysoev.ru static nxt_conf_map_t nxt_app_lang_module_map[] = { 1318240Sigor@sysoev.ru { 1319240Sigor@sysoev.ru nxt_string("type"), 1320356Svbart@nginx.com NXT_CONF_MAP_INT, 1321240Sigor@sysoev.ru offsetof(nxt_app_lang_module_t, type), 1322240Sigor@sysoev.ru }, 1323240Sigor@sysoev.ru 1324240Sigor@sysoev.ru { 1325240Sigor@sysoev.ru nxt_string("version"), 1326354Svbart@nginx.com NXT_CONF_MAP_CSTRZ, 1327240Sigor@sysoev.ru offsetof(nxt_app_lang_module_t, version), 1328240Sigor@sysoev.ru }, 1329240Sigor@sysoev.ru 1330240Sigor@sysoev.ru { 1331240Sigor@sysoev.ru nxt_string("file"), 1332240Sigor@sysoev.ru NXT_CONF_MAP_CSTRZ, 1333240Sigor@sysoev.ru offsetof(nxt_app_lang_module_t, file), 1334240Sigor@sysoev.ru }, 1335240Sigor@sysoev.ru }; 1336240Sigor@sysoev.ru 1337240Sigor@sysoev.ru 1338240Sigor@sysoev.ru static void 1339240Sigor@sysoev.ru nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1340240Sigor@sysoev.ru { 1341240Sigor@sysoev.ru uint32_t index; 1342240Sigor@sysoev.ru nxt_mp_t *mp; 1343240Sigor@sysoev.ru nxt_int_t ret; 1344240Sigor@sysoev.ru nxt_buf_t *b; 1345549Svbart@nginx.com nxt_port_t *port; 1346240Sigor@sysoev.ru nxt_runtime_t *rt; 1347240Sigor@sysoev.ru nxt_conf_value_t *conf, *root, *value; 1348240Sigor@sysoev.ru nxt_app_lang_module_t *lang; 1349240Sigor@sysoev.ru 13501182St.nateldemoura@f5.com static nxt_str_t root_path = nxt_string("/"); 1351240Sigor@sysoev.ru 1352240Sigor@sysoev.ru rt = task->thread->runtime; 1353240Sigor@sysoev.ru 1354240Sigor@sysoev.ru if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) { 1355240Sigor@sysoev.ru return; 1356240Sigor@sysoev.ru } 1357240Sigor@sysoev.ru 13581211Smax.romanov@nginx.com if (nxt_exiting) { 13591211Smax.romanov@nginx.com nxt_debug(task, "ignoring discovered modules, exiting"); 13601211Smax.romanov@nginx.com return; 13611211Smax.romanov@nginx.com } 13621211Smax.romanov@nginx.com 1363549Svbart@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 1364549Svbart@nginx.com msg->port_msg.reply_port); 1365549Svbart@nginx.com 1366549Svbart@nginx.com if (nxt_fast_path(port != NULL)) { 1367549Svbart@nginx.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, 1368549Svbart@nginx.com msg->port_msg.stream, 0, NULL); 1369549Svbart@nginx.com } 1370549Svbart@nginx.com 1371240Sigor@sysoev.ru b = msg->buf; 1372240Sigor@sysoev.ru 1373240Sigor@sysoev.ru if (b == NULL) { 1374240Sigor@sysoev.ru return; 1375240Sigor@sysoev.ru } 1376240Sigor@sysoev.ru 1377240Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 1378240Sigor@sysoev.ru if (mp == NULL) { 1379240Sigor@sysoev.ru return; 1380240Sigor@sysoev.ru } 1381240Sigor@sysoev.ru 1382352Smax.romanov@nginx.com b = nxt_buf_chk_make_plain(mp, b, msg->size); 1383352Smax.romanov@nginx.com 1384352Smax.romanov@nginx.com if (b == NULL) { 1385352Smax.romanov@nginx.com return; 1386352Smax.romanov@nginx.com } 1387352Smax.romanov@nginx.com 1388352Smax.romanov@nginx.com nxt_debug(task, "application languages: \"%*s\"", 1389352Smax.romanov@nginx.com b->mem.free - b->mem.pos, b->mem.pos); 1390352Smax.romanov@nginx.com 1391240Sigor@sysoev.ru conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL); 1392240Sigor@sysoev.ru if (conf == NULL) { 1393240Sigor@sysoev.ru goto fail; 1394240Sigor@sysoev.ru } 1395240Sigor@sysoev.ru 1396240Sigor@sysoev.ru root = nxt_conf_get_path(conf, &root_path); 1397240Sigor@sysoev.ru if (root == NULL) { 1398240Sigor@sysoev.ru goto fail; 1399240Sigor@sysoev.ru } 1400240Sigor@sysoev.ru 1401240Sigor@sysoev.ru for (index = 0; /* void */ ; index++) { 1402240Sigor@sysoev.ru value = nxt_conf_get_array_element(root, index); 1403240Sigor@sysoev.ru if (value == NULL) { 1404240Sigor@sysoev.ru break; 1405240Sigor@sysoev.ru } 1406240Sigor@sysoev.ru 1407240Sigor@sysoev.ru lang = nxt_array_add(rt->languages); 1408240Sigor@sysoev.ru if (lang == NULL) { 1409240Sigor@sysoev.ru goto fail; 1410240Sigor@sysoev.ru } 1411240Sigor@sysoev.ru 1412240Sigor@sysoev.ru lang->module = NULL; 1413240Sigor@sysoev.ru 1414240Sigor@sysoev.ru ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map, 1415240Sigor@sysoev.ru nxt_nitems(nxt_app_lang_module_map), lang); 1416240Sigor@sysoev.ru 1417240Sigor@sysoev.ru if (ret != NXT_OK) { 1418240Sigor@sysoev.ru goto fail; 1419240Sigor@sysoev.ru } 1420240Sigor@sysoev.ru 1421356Svbart@nginx.com nxt_debug(task, "lang %d %s \"%s\"", 1422356Svbart@nginx.com lang->type, lang->version, lang->file); 1423240Sigor@sysoev.ru } 1424240Sigor@sysoev.ru 1425240Sigor@sysoev.ru qsort(rt->languages->elts, rt->languages->nelts, 1426240Sigor@sysoev.ru sizeof(nxt_app_lang_module_t), nxt_app_lang_compare); 1427240Sigor@sysoev.ru 1428240Sigor@sysoev.ru fail: 1429240Sigor@sysoev.ru 1430240Sigor@sysoev.ru nxt_mp_destroy(mp); 1431240Sigor@sysoev.ru 1432240Sigor@sysoev.ru ret = nxt_main_start_controller_process(task, rt); 1433240Sigor@sysoev.ru 1434240Sigor@sysoev.ru if (ret == NXT_OK) { 1435240Sigor@sysoev.ru (void) nxt_main_start_router_process(task, rt); 1436240Sigor@sysoev.ru } 1437240Sigor@sysoev.ru } 1438240Sigor@sysoev.ru 1439240Sigor@sysoev.ru 1440240Sigor@sysoev.ru static int nxt_cdecl 1441240Sigor@sysoev.ru nxt_app_lang_compare(const void *v1, const void *v2) 1442240Sigor@sysoev.ru { 1443240Sigor@sysoev.ru int n; 1444240Sigor@sysoev.ru const nxt_app_lang_module_t *lang1, *lang2; 1445240Sigor@sysoev.ru 1446240Sigor@sysoev.ru lang1 = v1; 1447240Sigor@sysoev.ru lang2 = v2; 1448240Sigor@sysoev.ru 1449356Svbart@nginx.com n = lang1->type - lang2->type; 1450258Sigor@sysoev.ru 1451258Sigor@sysoev.ru if (n != 0) { 1452258Sigor@sysoev.ru return n; 1453258Sigor@sysoev.ru } 1454258Sigor@sysoev.ru 1455354Svbart@nginx.com n = nxt_strverscmp(lang1->version, lang2->version); 1456240Sigor@sysoev.ru 1457240Sigor@sysoev.ru /* Negate result to move higher versions to the beginning. */ 1458240Sigor@sysoev.ru 1459240Sigor@sysoev.ru return -n; 1460240Sigor@sysoev.ru } 1461314Svbart@nginx.com 1462314Svbart@nginx.com 1463314Svbart@nginx.com static void 1464314Svbart@nginx.com nxt_main_port_conf_store_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1465314Svbart@nginx.com { 1466352Smax.romanov@nginx.com ssize_t n, size, offset; 1467314Svbart@nginx.com nxt_buf_t *b; 1468314Svbart@nginx.com nxt_int_t ret; 1469314Svbart@nginx.com nxt_file_t file; 1470314Svbart@nginx.com nxt_runtime_t *rt; 1471314Svbart@nginx.com 1472314Svbart@nginx.com nxt_memzero(&file, sizeof(nxt_file_t)); 1473314Svbart@nginx.com 1474314Svbart@nginx.com rt = task->thread->runtime; 1475314Svbart@nginx.com 1476314Svbart@nginx.com file.name = (nxt_file_name_t *) rt->conf_tmp; 1477314Svbart@nginx.com 1478314Svbart@nginx.com if (nxt_slow_path(nxt_file_open(task, &file, NXT_FILE_WRONLY, 1479314Svbart@nginx.com NXT_FILE_TRUNCATE, NXT_FILE_OWNER_ACCESS) 1480314Svbart@nginx.com != NXT_OK)) 1481314Svbart@nginx.com { 1482314Svbart@nginx.com goto error; 1483314Svbart@nginx.com } 1484314Svbart@nginx.com 1485352Smax.romanov@nginx.com offset = 0; 1486352Smax.romanov@nginx.com 1487314Svbart@nginx.com for (b = msg->buf; b != NULL; b = b->next) { 1488314Svbart@nginx.com size = nxt_buf_mem_used_size(&b->mem); 1489314Svbart@nginx.com 1490352Smax.romanov@nginx.com n = nxt_file_write(&file, b->mem.pos, size, offset); 1491314Svbart@nginx.com 1492314Svbart@nginx.com if (nxt_slow_path(n != size)) { 1493314Svbart@nginx.com nxt_file_close(task, &file); 1494314Svbart@nginx.com (void) nxt_file_delete(file.name); 1495314Svbart@nginx.com goto error; 1496314Svbart@nginx.com } 1497352Smax.romanov@nginx.com 1498352Smax.romanov@nginx.com offset += n; 1499314Svbart@nginx.com } 1500314Svbart@nginx.com 1501314Svbart@nginx.com nxt_file_close(task, &file); 1502314Svbart@nginx.com 1503314Svbart@nginx.com ret = nxt_file_rename(file.name, (nxt_file_name_t *) rt->conf); 1504314Svbart@nginx.com 1505314Svbart@nginx.com if (nxt_fast_path(ret == NXT_OK)) { 1506314Svbart@nginx.com return; 1507314Svbart@nginx.com } 1508314Svbart@nginx.com 1509314Svbart@nginx.com error: 1510314Svbart@nginx.com 1511564Svbart@nginx.com nxt_alert(task, "failed to store current configuration"); 1512314Svbart@nginx.com } 1513630Svbart@nginx.com 1514630Svbart@nginx.com 1515630Svbart@nginx.com static void 1516630Svbart@nginx.com nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1517630Svbart@nginx.com { 1518630Svbart@nginx.com u_char *path; 1519630Svbart@nginx.com nxt_int_t ret; 1520630Svbart@nginx.com nxt_file_t file; 1521630Svbart@nginx.com nxt_port_t *port; 1522630Svbart@nginx.com nxt_port_msg_type_t type; 1523630Svbart@nginx.com 1524630Svbart@nginx.com nxt_debug(task, "opening access log file"); 1525630Svbart@nginx.com 1526630Svbart@nginx.com path = msg->buf->mem.pos; 1527630Svbart@nginx.com 1528630Svbart@nginx.com nxt_memzero(&file, sizeof(nxt_file_t)); 1529630Svbart@nginx.com 1530630Svbart@nginx.com file.name = (nxt_file_name_t *) path; 1531630Svbart@nginx.com file.log_level = NXT_LOG_ERR; 1532630Svbart@nginx.com 1533630Svbart@nginx.com ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, 1534630Svbart@nginx.com NXT_FILE_OWNER_ACCESS); 1535630Svbart@nginx.com 1536630Svbart@nginx.com type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD 1537630Svbart@nginx.com : NXT_PORT_MSG_RPC_ERROR; 1538630Svbart@nginx.com 1539630Svbart@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 1540630Svbart@nginx.com msg->port_msg.reply_port); 1541630Svbart@nginx.com 1542630Svbart@nginx.com if (nxt_fast_path(port != NULL)) { 1543630Svbart@nginx.com (void) nxt_port_socket_write(task, port, type, file.fd, 1544630Svbart@nginx.com msg->port_msg.stream, 0, NULL); 1545630Svbart@nginx.com } 1546630Svbart@nginx.com } 15471182St.nateldemoura@f5.com 15481182St.nateldemoura@f5.com 15491182St.nateldemoura@f5.com static nxt_int_t 15501306St.nateldemoura@f5.com nxt_init_isolation(nxt_task_t *task, nxt_conf_value_t *isolation, 15511306St.nateldemoura@f5.com nxt_process_init_t *init) 15521306St.nateldemoura@f5.com { 15531306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 15541306St.nateldemoura@f5.com nxt_int_t ret; 15551306St.nateldemoura@f5.com nxt_conf_value_t *obj; 15561306St.nateldemoura@f5.com 15571306St.nateldemoura@f5.com static nxt_str_t nsname = nxt_string("namespaces"); 15581306St.nateldemoura@f5.com 15591306St.nateldemoura@f5.com obj = nxt_conf_get_object_member(isolation, &nsname, NULL); 15601306St.nateldemoura@f5.com if (obj != NULL) { 15611306St.nateldemoura@f5.com ret = nxt_init_clone_flags(task, obj, init); 15621306St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 15631306St.nateldemoura@f5.com return NXT_ERROR; 15641306St.nateldemoura@f5.com } 15651306St.nateldemoura@f5.com } 15661306St.nateldemoura@f5.com #endif 15671306St.nateldemoura@f5.com 15681306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 15691306St.nateldemoura@f5.com ret = nxt_init_isolation_creds(task, isolation, init); 15701306St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 15711306St.nateldemoura@f5.com return NXT_ERROR; 15721306St.nateldemoura@f5.com } 15731306St.nateldemoura@f5.com #endif 15741306St.nateldemoura@f5.com 15751306St.nateldemoura@f5.com return NXT_OK; 15761306St.nateldemoura@f5.com } 15771306St.nateldemoura@f5.com 15781306St.nateldemoura@f5.com 15791306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 15801306St.nateldemoura@f5.com 15811306St.nateldemoura@f5.com static nxt_int_t 15821306St.nateldemoura@f5.com nxt_init_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation, 15831306St.nateldemoura@f5.com nxt_process_init_t *init) 15841182St.nateldemoura@f5.com { 15851182St.nateldemoura@f5.com nxt_int_t ret; 15861306St.nateldemoura@f5.com nxt_clone_t *clone; 15871306St.nateldemoura@f5.com nxt_conf_value_t *array; 15881182St.nateldemoura@f5.com 15891182St.nateldemoura@f5.com static nxt_str_t uidname = nxt_string("uidmap"); 15901182St.nateldemoura@f5.com static nxt_str_t gidname = nxt_string("gidmap"); 15911182St.nateldemoura@f5.com 15921306St.nateldemoura@f5.com clone = &init->isolation.clone; 15931182St.nateldemoura@f5.com 15941306St.nateldemoura@f5.com array = nxt_conf_get_object_member(isolation, &uidname, NULL); 15951306St.nateldemoura@f5.com if (array != NULL) { 15961306St.nateldemoura@f5.com ret = nxt_init_isolation_credential_map(task, init->mem_pool, array, 15971306St.nateldemoura@f5.com &clone->uidmap); 15981306St.nateldemoura@f5.com 15991306St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 16001306St.nateldemoura@f5.com return NXT_ERROR; 16011182St.nateldemoura@f5.com } 16021182St.nateldemoura@f5.com } 16031182St.nateldemoura@f5.com 16041306St.nateldemoura@f5.com array = nxt_conf_get_object_member(isolation, &gidname, NULL); 16051306St.nateldemoura@f5.com if (array != NULL) { 16061306St.nateldemoura@f5.com ret = nxt_init_isolation_credential_map(task, init->mem_pool, array, 16071306St.nateldemoura@f5.com &clone->gidmap); 16081182St.nateldemoura@f5.com 16091306St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 16101306St.nateldemoura@f5.com return NXT_ERROR; 16111306St.nateldemoura@f5.com } 16121182St.nateldemoura@f5.com } 16131182St.nateldemoura@f5.com 16141182St.nateldemoura@f5.com return NXT_OK; 16151182St.nateldemoura@f5.com } 16161182St.nateldemoura@f5.com 16171182St.nateldemoura@f5.com 16181182St.nateldemoura@f5.com static nxt_int_t 16191306St.nateldemoura@f5.com nxt_init_vldt_isolation_creds(nxt_task_t *task, nxt_process_init_t *init) 16201306St.nateldemoura@f5.com { 16211306St.nateldemoura@f5.com nxt_int_t ret; 16221306St.nateldemoura@f5.com nxt_clone_t *clone; 16231306St.nateldemoura@f5.com 16241306St.nateldemoura@f5.com clone = &init->isolation.clone; 16251306St.nateldemoura@f5.com 16261306St.nateldemoura@f5.com if (clone->uidmap.size == 0 && clone->gidmap.size == 0) { 16271306St.nateldemoura@f5.com return NXT_OK; 16281306St.nateldemoura@f5.com } 16291306St.nateldemoura@f5.com 16301306St.nateldemoura@f5.com if (!NXT_CLONE_USER(clone->flags)) { 16311306St.nateldemoura@f5.com if (nxt_slow_path(clone->uidmap.size > 0)) { 16321306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"uidmap\" is set but " 16331306St.nateldemoura@f5.com "\"isolation.namespaces.credential\" is false or unset"); 16341306St.nateldemoura@f5.com 16351306St.nateldemoura@f5.com return NXT_ERROR; 16361306St.nateldemoura@f5.com } 16371306St.nateldemoura@f5.com 16381306St.nateldemoura@f5.com if (nxt_slow_path(clone->gidmap.size > 0)) { 16391306St.nateldemoura@f5.com nxt_log(task, NXT_LOG_ERR, "\"gidmap\" is set but " 16401306St.nateldemoura@f5.com "\"isolation.namespaces.credential\" is false or unset"); 16411306St.nateldemoura@f5.com 16421306St.nateldemoura@f5.com return NXT_ERROR; 16431306St.nateldemoura@f5.com } 16441306St.nateldemoura@f5.com 16451306St.nateldemoura@f5.com return NXT_OK; 16461306St.nateldemoura@f5.com } 16471306St.nateldemoura@f5.com 16481306St.nateldemoura@f5.com ret = nxt_clone_vldt_credential_uidmap(task, &clone->uidmap, 16491306St.nateldemoura@f5.com init->user_cred); 16501306St.nateldemoura@f5.com 16511306St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 16521306St.nateldemoura@f5.com return NXT_ERROR; 16531306St.nateldemoura@f5.com } 16541306St.nateldemoura@f5.com 16551306St.nateldemoura@f5.com return nxt_clone_vldt_credential_gidmap(task, &clone->gidmap, 16561306St.nateldemoura@f5.com init->user_cred); 16571306St.nateldemoura@f5.com } 16581306St.nateldemoura@f5.com 16591306St.nateldemoura@f5.com 16601306St.nateldemoura@f5.com static nxt_int_t 16611306St.nateldemoura@f5.com nxt_init_isolation_credential_map(nxt_task_t *task, nxt_mp_t *mem_pool, 16621306St.nateldemoura@f5.com nxt_conf_value_t *map_array, nxt_clone_credential_map_t *map) 16631306St.nateldemoura@f5.com { 16641306St.nateldemoura@f5.com nxt_int_t ret; 16651306St.nateldemoura@f5.com nxt_uint_t i; 16661306St.nateldemoura@f5.com nxt_conf_value_t *obj; 16671306St.nateldemoura@f5.com 16681306St.nateldemoura@f5.com static nxt_conf_map_t nxt_clone_map_entry_conf[] = { 16691306St.nateldemoura@f5.com { 16701306St.nateldemoura@f5.com nxt_string("container"), 16711306St.nateldemoura@f5.com NXT_CONF_MAP_INT, 16721306St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, container), 16731306St.nateldemoura@f5.com }, 16741306St.nateldemoura@f5.com 16751306St.nateldemoura@f5.com { 16761306St.nateldemoura@f5.com nxt_string("host"), 16771306St.nateldemoura@f5.com NXT_CONF_MAP_INT, 16781306St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, host), 16791306St.nateldemoura@f5.com }, 16801306St.nateldemoura@f5.com 16811306St.nateldemoura@f5.com { 16821306St.nateldemoura@f5.com nxt_string("size"), 16831306St.nateldemoura@f5.com NXT_CONF_MAP_INT, 16841306St.nateldemoura@f5.com offsetof(nxt_clone_map_entry_t, size), 16851306St.nateldemoura@f5.com }, 16861306St.nateldemoura@f5.com }; 16871306St.nateldemoura@f5.com 16881306St.nateldemoura@f5.com map->size = nxt_conf_array_elements_count(map_array); 16891306St.nateldemoura@f5.com 16901306St.nateldemoura@f5.com if (map->size == 0) { 16911306St.nateldemoura@f5.com return NXT_OK; 16921306St.nateldemoura@f5.com } 16931306St.nateldemoura@f5.com 16941306St.nateldemoura@f5.com map->map = nxt_mp_alloc(mem_pool, 16951306St.nateldemoura@f5.com map->size * sizeof(nxt_clone_map_entry_t)); 16961306St.nateldemoura@f5.com if (nxt_slow_path(map->map == NULL)) { 16971306St.nateldemoura@f5.com return NXT_ERROR; 16981306St.nateldemoura@f5.com } 16991306St.nateldemoura@f5.com 17001306St.nateldemoura@f5.com for (i = 0; i < map->size; i++) { 17011306St.nateldemoura@f5.com obj = nxt_conf_get_array_element(map_array, i); 17021306St.nateldemoura@f5.com 17031306St.nateldemoura@f5.com ret = nxt_conf_map_object(mem_pool, obj, nxt_clone_map_entry_conf, 17041306St.nateldemoura@f5.com nxt_nitems(nxt_clone_map_entry_conf), 17051306St.nateldemoura@f5.com map->map + i); 17061306St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 17071306St.nateldemoura@f5.com nxt_alert(task, "clone map entry map error"); 17081306St.nateldemoura@f5.com return NXT_ERROR; 17091306St.nateldemoura@f5.com } 17101306St.nateldemoura@f5.com } 17111306St.nateldemoura@f5.com 17121306St.nateldemoura@f5.com return NXT_OK; 17131306St.nateldemoura@f5.com } 17141306St.nateldemoura@f5.com 17151306St.nateldemoura@f5.com #endif 17161306St.nateldemoura@f5.com 17171306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE) 17181306St.nateldemoura@f5.com 17191306St.nateldemoura@f5.com static nxt_int_t 17201306St.nateldemoura@f5.com nxt_init_clone_flags(nxt_task_t *task, nxt_conf_value_t *namespaces, 17211306St.nateldemoura@f5.com nxt_process_init_t *init) 17221182St.nateldemoura@f5.com { 17231182St.nateldemoura@f5.com uint32_t index; 17241182St.nateldemoura@f5.com nxt_str_t name; 17251182St.nateldemoura@f5.com nxt_int_t flag; 17261182St.nateldemoura@f5.com nxt_conf_value_t *value; 17271182St.nateldemoura@f5.com 17281182St.nateldemoura@f5.com index = 0; 17291182St.nateldemoura@f5.com 17301235Sigor@sysoev.ru for ( ;; ) { 17311235Sigor@sysoev.ru value = nxt_conf_next_object_member(namespaces, &name, &index); 17321235Sigor@sysoev.ru 17331235Sigor@sysoev.ru if (value == NULL) { 17341235Sigor@sysoev.ru break; 17351235Sigor@sysoev.ru } 17361235Sigor@sysoev.ru 17371182St.nateldemoura@f5.com flag = 0; 17381182St.nateldemoura@f5.com 17391182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER) 17401182St.nateldemoura@f5.com if (nxt_str_eq(&name, "credential", 10)) { 17411182St.nateldemoura@f5.com flag = CLONE_NEWUSER; 17421182St.nateldemoura@f5.com } 17431182St.nateldemoura@f5.com #endif 17441182St.nateldemoura@f5.com 17451182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWPID) 17461182St.nateldemoura@f5.com if (nxt_str_eq(&name, "pid", 3)) { 17471182St.nateldemoura@f5.com flag = CLONE_NEWPID; 17481182St.nateldemoura@f5.com } 17491182St.nateldemoura@f5.com #endif 17501182St.nateldemoura@f5.com 17511182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNET) 17521182St.nateldemoura@f5.com if (nxt_str_eq(&name, "network", 7)) { 17531182St.nateldemoura@f5.com flag = CLONE_NEWNET; 17541182St.nateldemoura@f5.com } 17551182St.nateldemoura@f5.com #endif 17561182St.nateldemoura@f5.com 17571182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUTS) 17581182St.nateldemoura@f5.com if (nxt_str_eq(&name, "uname", 5)) { 17591182St.nateldemoura@f5.com flag = CLONE_NEWUTS; 17601182St.nateldemoura@f5.com } 17611182St.nateldemoura@f5.com #endif 17621182St.nateldemoura@f5.com 17631182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNS) 17641182St.nateldemoura@f5.com if (nxt_str_eq(&name, "mount", 5)) { 17651182St.nateldemoura@f5.com flag = CLONE_NEWNS; 17661182St.nateldemoura@f5.com } 17671182St.nateldemoura@f5.com #endif 17681182St.nateldemoura@f5.com 17691182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWCGROUP) 17701182St.nateldemoura@f5.com if (nxt_str_eq(&name, "cgroup", 6)) { 17711182St.nateldemoura@f5.com flag = CLONE_NEWCGROUP; 17721182St.nateldemoura@f5.com } 17731182St.nateldemoura@f5.com #endif 17741182St.nateldemoura@f5.com 17751182St.nateldemoura@f5.com if (!flag) { 17761182St.nateldemoura@f5.com nxt_alert(task, "unknown namespace flag: \"%V\"", &name); 17771182St.nateldemoura@f5.com return NXT_ERROR; 17781182St.nateldemoura@f5.com } 17791182St.nateldemoura@f5.com 17801236St.nateldemoura@f5.com if (nxt_conf_get_boolean(value)) { 17811236St.nateldemoura@f5.com init->isolation.clone.flags |= flag; 17821182St.nateldemoura@f5.com } 17831182St.nateldemoura@f5.com } 17841182St.nateldemoura@f5.com 17851182St.nateldemoura@f5.com return NXT_OK; 17861182St.nateldemoura@f5.com } 17871302St.nateldemoura@f5.com 17881306St.nateldemoura@f5.com #endif 17891306St.nateldemoura@f5.com 17901302St.nateldemoura@f5.com 17911302St.nateldemoura@f5.com static nxt_process_init_t * 17921302St.nateldemoura@f5.com nxt_process_init_create(nxt_task_t *task, nxt_process_type_t type, 17931302St.nateldemoura@f5.com const nxt_str_t *name) 17941302St.nateldemoura@f5.com { 17951302St.nateldemoura@f5.com nxt_mp_t *mp; 17961302St.nateldemoura@f5.com nxt_int_t ret; 17971302St.nateldemoura@f5.com nxt_runtime_t *rt; 17981302St.nateldemoura@f5.com nxt_process_init_t *init; 17991302St.nateldemoura@f5.com 18001302St.nateldemoura@f5.com mp = nxt_mp_create(1024, 128, 256, 32); 18011302St.nateldemoura@f5.com if (nxt_slow_path(mp == NULL)) { 18021302St.nateldemoura@f5.com return NULL; 18031302St.nateldemoura@f5.com } 18041302St.nateldemoura@f5.com 18051302St.nateldemoura@f5.com init = nxt_mp_zalloc(mp, sizeof(nxt_process_init_t)); 18061302St.nateldemoura@f5.com if (nxt_slow_path(init == NULL)) { 18071302St.nateldemoura@f5.com goto fail; 18081302St.nateldemoura@f5.com } 18091302St.nateldemoura@f5.com 18101302St.nateldemoura@f5.com init->mem_pool = mp; 18111302St.nateldemoura@f5.com 18121302St.nateldemoura@f5.com ret = nxt_process_init_name_set(init, type, name); 18131302St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 18141302St.nateldemoura@f5.com goto fail; 18151302St.nateldemoura@f5.com } 18161302St.nateldemoura@f5.com 18171302St.nateldemoura@f5.com rt = task->thread->runtime; 18181302St.nateldemoura@f5.com 18191302St.nateldemoura@f5.com init->type = type; 18201302St.nateldemoura@f5.com init->start = nxt_process_starts[type]; 18211302St.nateldemoura@f5.com init->port_handlers = nxt_process_port_handlers[type]; 18221302St.nateldemoura@f5.com init->signals = nxt_worker_process_signals; 18231302St.nateldemoura@f5.com init->user_cred = &rt->user_cred; 18241302St.nateldemoura@f5.com init->data = &rt; 18251302St.nateldemoura@f5.com 18261302St.nateldemoura@f5.com return init; 18271302St.nateldemoura@f5.com 18281302St.nateldemoura@f5.com fail: 18291302St.nateldemoura@f5.com 18301302St.nateldemoura@f5.com nxt_mp_destroy(mp); 18311302St.nateldemoura@f5.com 18321302St.nateldemoura@f5.com return NULL; 18331302St.nateldemoura@f5.com } 18341302St.nateldemoura@f5.com 18351302St.nateldemoura@f5.com 18361302St.nateldemoura@f5.com static nxt_int_t 18371302St.nateldemoura@f5.com nxt_process_init_name_set(nxt_process_init_t *init, nxt_process_type_t type, 18381302St.nateldemoura@f5.com const nxt_str_t *name) 18391302St.nateldemoura@f5.com { 18401302St.nateldemoura@f5.com u_char *str, *end; 18411302St.nateldemoura@f5.com size_t size; 18421302St.nateldemoura@f5.com const char *fmt; 18431302St.nateldemoura@f5.com 18441302St.nateldemoura@f5.com size = name->length + 1; 18451302St.nateldemoura@f5.com 18461302St.nateldemoura@f5.com if (type == NXT_PROCESS_WORKER) { 18471302St.nateldemoura@f5.com size += nxt_length("\"\" application"); 18481302St.nateldemoura@f5.com fmt = "\"%V\" application%Z"; 18491302St.nateldemoura@f5.com 18501302St.nateldemoura@f5.com } else { 18511302St.nateldemoura@f5.com fmt = "%V%Z"; 18521302St.nateldemoura@f5.com } 18531302St.nateldemoura@f5.com 18541302St.nateldemoura@f5.com str = nxt_mp_alloc(init->mem_pool, size); 18551302St.nateldemoura@f5.com if (nxt_slow_path(str == NULL)) { 18561302St.nateldemoura@f5.com return NXT_ERROR; 18571302St.nateldemoura@f5.com } 18581302St.nateldemoura@f5.com 18591302St.nateldemoura@f5.com end = str + size; 18601302St.nateldemoura@f5.com 18611302St.nateldemoura@f5.com nxt_sprintf(str, end, fmt, name); 18621302St.nateldemoura@f5.com 18631302St.nateldemoura@f5.com init->name = (char *) str; 18641302St.nateldemoura@f5.com 18651302St.nateldemoura@f5.com return NXT_OK; 18661302St.nateldemoura@f5.com } 18671302St.nateldemoura@f5.com 18681302St.nateldemoura@f5.com 18691302St.nateldemoura@f5.com static nxt_int_t 18701302St.nateldemoura@f5.com nxt_process_init_creds_set(nxt_task_t *task, nxt_process_init_t *init, 18711302St.nateldemoura@f5.com nxt_str_t *user, nxt_str_t *group) 18721302St.nateldemoura@f5.com { 18731302St.nateldemoura@f5.com char *str; 18741302St.nateldemoura@f5.com 18751305St.nateldemoura@f5.com init->user_cred = nxt_mp_zalloc(init->mem_pool, sizeof(nxt_credential_t)); 18761302St.nateldemoura@f5.com 18771302St.nateldemoura@f5.com if (nxt_slow_path(init->user_cred == NULL)) { 18781302St.nateldemoura@f5.com return NXT_ERROR; 18791302St.nateldemoura@f5.com } 18801302St.nateldemoura@f5.com 18811302St.nateldemoura@f5.com str = nxt_mp_zalloc(init->mem_pool, user->length + 1); 18821302St.nateldemoura@f5.com if (nxt_slow_path(str == NULL)) { 18831302St.nateldemoura@f5.com return NXT_ERROR; 18841302St.nateldemoura@f5.com } 18851302St.nateldemoura@f5.com 18861302St.nateldemoura@f5.com nxt_memcpy(str, user->start, user->length); 18871302St.nateldemoura@f5.com str[user->length] = '\0'; 18881302St.nateldemoura@f5.com 18891302St.nateldemoura@f5.com init->user_cred->user = str; 18901302St.nateldemoura@f5.com 18911302St.nateldemoura@f5.com if (group->start != NULL) { 18921302St.nateldemoura@f5.com str = nxt_mp_zalloc(init->mem_pool, group->length + 1); 18931302St.nateldemoura@f5.com if (nxt_slow_path(str == NULL)) { 18941302St.nateldemoura@f5.com return NXT_ERROR; 18951302St.nateldemoura@f5.com } 18961302St.nateldemoura@f5.com 18971302St.nateldemoura@f5.com nxt_memcpy(str, group->start, group->length); 18981302St.nateldemoura@f5.com str[group->length] = '\0'; 18991302St.nateldemoura@f5.com 19001302St.nateldemoura@f5.com } else { 19011302St.nateldemoura@f5.com str = NULL; 19021302St.nateldemoura@f5.com } 19031302St.nateldemoura@f5.com 19041305St.nateldemoura@f5.com return nxt_credential_get(task, init->mem_pool, init->user_cred, str); 19051302St.nateldemoura@f5.com } 1906