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 171489St.nateldemoura@f5.com #include <sys/mount.h> 181489St.nateldemoura@f5.com 19240Sigor@sysoev.ru 20240Sigor@sysoev.ru typedef struct { 21240Sigor@sysoev.ru nxt_socket_t socket; 22240Sigor@sysoev.ru nxt_socket_error_t error; 23240Sigor@sysoev.ru u_char *start; 24240Sigor@sysoev.ru u_char *end; 25240Sigor@sysoev.ru } nxt_listening_socket_t; 26240Sigor@sysoev.ru 27240Sigor@sysoev.ru 28510Salexander.borisov@nginx.com typedef struct { 29536Svbart@nginx.com nxt_uint_t size; 30536Svbart@nginx.com nxt_conf_map_t *map; 31546Smax.romanov@nginx.com } nxt_conf_app_map_t; 32510Salexander.borisov@nginx.com 33510Salexander.borisov@nginx.com 341302St.nateldemoura@f5.com extern nxt_port_handlers_t nxt_controller_process_port_handlers; 351302St.nateldemoura@f5.com extern nxt_port_handlers_t nxt_router_process_port_handlers; 361302St.nateldemoura@f5.com 371302St.nateldemoura@f5.com 38240Sigor@sysoev.ru static nxt_int_t nxt_main_process_port_create(nxt_task_t *task, 39240Sigor@sysoev.ru nxt_runtime_t *rt); 40240Sigor@sysoev.ru static void nxt_main_process_title(nxt_task_t *task); 411488St.nateldemoura@f5.com static nxt_int_t nxt_main_process_create(nxt_task_t *task, 421488St.nateldemoura@f5.com const nxt_process_init_t init); 431488St.nateldemoura@f5.com static nxt_int_t nxt_main_start_process(nxt_task_t *task, 441488St.nateldemoura@f5.com nxt_process_t *process); 451488St.nateldemoura@f5.com static nxt_process_t *nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt); 46240Sigor@sysoev.ru static void nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, 47240Sigor@sysoev.ru void *data); 48240Sigor@sysoev.ru static void nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, 49240Sigor@sysoev.ru void *data); 50240Sigor@sysoev.ru static void nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, 51240Sigor@sysoev.ru void *data); 52240Sigor@sysoev.ru static void nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, 53240Sigor@sysoev.ru void *data); 54944Sigor@sysoev.ru static void nxt_main_process_signal_handler(nxt_task_t *task, void *obj, 55944Sigor@sysoev.ru void *data); 561488St.nateldemoura@f5.com static void nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid); 57240Sigor@sysoev.ru static void nxt_main_port_socket_handler(nxt_task_t *task, 58240Sigor@sysoev.ru nxt_port_recv_msg_t *msg); 59240Sigor@sysoev.ru static nxt_int_t nxt_main_listening_socket(nxt_sockaddr_t *sa, 60240Sigor@sysoev.ru nxt_listening_socket_t *ls); 61240Sigor@sysoev.ru static void nxt_main_port_modules_handler(nxt_task_t *task, 62240Sigor@sysoev.ru nxt_port_recv_msg_t *msg); 63240Sigor@sysoev.ru static int nxt_cdecl nxt_app_lang_compare(const void *v1, const void *v2); 64314Svbart@nginx.com static void nxt_main_port_conf_store_handler(nxt_task_t *task, 65314Svbart@nginx.com nxt_port_recv_msg_t *msg); 66630Svbart@nginx.com static void nxt_main_port_access_log_handler(nxt_task_t *task, 67630Svbart@nginx.com nxt_port_recv_msg_t *msg); 68240Sigor@sysoev.ru 69240Sigor@sysoev.ru const nxt_sig_event_t nxt_main_process_signals[] = { 70944Sigor@sysoev.ru nxt_event_signal(SIGHUP, nxt_main_process_signal_handler), 71240Sigor@sysoev.ru nxt_event_signal(SIGINT, nxt_main_process_sigterm_handler), 72240Sigor@sysoev.ru nxt_event_signal(SIGQUIT, nxt_main_process_sigquit_handler), 73240Sigor@sysoev.ru nxt_event_signal(SIGTERM, nxt_main_process_sigterm_handler), 74240Sigor@sysoev.ru nxt_event_signal(SIGCHLD, nxt_main_process_sigchld_handler), 75240Sigor@sysoev.ru nxt_event_signal(SIGUSR1, nxt_main_process_sigusr1_handler), 76240Sigor@sysoev.ru nxt_event_signal_end, 77240Sigor@sysoev.ru }; 78240Sigor@sysoev.ru 79240Sigor@sysoev.ru 80240Sigor@sysoev.ru static nxt_bool_t nxt_exiting; 81240Sigor@sysoev.ru 82240Sigor@sysoev.ru 83240Sigor@sysoev.ru nxt_int_t 84240Sigor@sysoev.ru nxt_main_process_start(nxt_thread_t *thr, nxt_task_t *task, 85240Sigor@sysoev.ru nxt_runtime_t *rt) 86240Sigor@sysoev.ru { 87696Sigor@sysoev.ru rt->type = NXT_PROCESS_MAIN; 88240Sigor@sysoev.ru 89240Sigor@sysoev.ru if (nxt_main_process_port_create(task, rt) != NXT_OK) { 90240Sigor@sysoev.ru return NXT_ERROR; 91240Sigor@sysoev.ru } 92240Sigor@sysoev.ru 93240Sigor@sysoev.ru nxt_main_process_title(task); 94240Sigor@sysoev.ru 95240Sigor@sysoev.ru /* 961488St.nateldemoura@f5.com * The discovery process will send a message processed by 97240Sigor@sysoev.ru * nxt_main_port_modules_handler() which starts the controller 98240Sigor@sysoev.ru * and router processes. 99240Sigor@sysoev.ru */ 1001488St.nateldemoura@f5.com return nxt_main_process_create(task, nxt_discovery_process); 101240Sigor@sysoev.ru } 102240Sigor@sysoev.ru 103240Sigor@sysoev.ru 104240Sigor@sysoev.ru static nxt_conf_map_t nxt_common_app_conf[] = { 105240Sigor@sysoev.ru { 106240Sigor@sysoev.ru nxt_string("type"), 107240Sigor@sysoev.ru NXT_CONF_MAP_STR, 108240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, type), 109240Sigor@sysoev.ru }, 110240Sigor@sysoev.ru 111240Sigor@sysoev.ru { 112240Sigor@sysoev.ru nxt_string("user"), 113240Sigor@sysoev.ru NXT_CONF_MAP_STR, 114240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, user), 115240Sigor@sysoev.ru }, 116240Sigor@sysoev.ru 117240Sigor@sysoev.ru { 118240Sigor@sysoev.ru nxt_string("group"), 119240Sigor@sysoev.ru NXT_CONF_MAP_STR, 120240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, group), 121240Sigor@sysoev.ru }, 122240Sigor@sysoev.ru 123240Sigor@sysoev.ru { 124271Smax.romanov@nginx.com nxt_string("working_directory"), 125271Smax.romanov@nginx.com NXT_CONF_MAP_CSTRZ, 126271Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, working_directory), 127271Smax.romanov@nginx.com }, 128678Svbart@nginx.com 129678Svbart@nginx.com { 130678Svbart@nginx.com nxt_string("environment"), 131678Svbart@nginx.com NXT_CONF_MAP_PTR, 132678Svbart@nginx.com offsetof(nxt_common_app_conf_t, environment), 133678Svbart@nginx.com }, 1341182St.nateldemoura@f5.com 1351182St.nateldemoura@f5.com { 1361182St.nateldemoura@f5.com nxt_string("isolation"), 1371182St.nateldemoura@f5.com NXT_CONF_MAP_PTR, 1381182St.nateldemoura@f5.com offsetof(nxt_common_app_conf_t, isolation), 1391320Smax.romanov@nginx.com }, 1401320Smax.romanov@nginx.com 1411320Smax.romanov@nginx.com { 1421320Smax.romanov@nginx.com nxt_string("limits"), 1431320Smax.romanov@nginx.com NXT_CONF_MAP_PTR, 1441320Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, limits), 1451320Smax.romanov@nginx.com }, 1461320Smax.romanov@nginx.com 1471320Smax.romanov@nginx.com }; 1481320Smax.romanov@nginx.com 1491320Smax.romanov@nginx.com 1501320Smax.romanov@nginx.com static nxt_conf_map_t nxt_common_app_limits_conf[] = { 1511320Smax.romanov@nginx.com { 1521320Smax.romanov@nginx.com nxt_string("shm"), 1531320Smax.romanov@nginx.com NXT_CONF_MAP_SIZE, 1541320Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, shm_limit), 1551320Smax.romanov@nginx.com }, 1561320Smax.romanov@nginx.com 157510Salexander.borisov@nginx.com }; 158271Smax.romanov@nginx.com 159510Salexander.borisov@nginx.com 160804Svbart@nginx.com static nxt_conf_map_t nxt_external_app_conf[] = { 161804Svbart@nginx.com { 162804Svbart@nginx.com nxt_string("executable"), 163804Svbart@nginx.com NXT_CONF_MAP_CSTRZ, 164804Svbart@nginx.com offsetof(nxt_common_app_conf_t, u.external.executable), 165804Svbart@nginx.com }, 166804Svbart@nginx.com 167804Svbart@nginx.com { 168804Svbart@nginx.com nxt_string("arguments"), 169804Svbart@nginx.com NXT_CONF_MAP_PTR, 170804Svbart@nginx.com offsetof(nxt_common_app_conf_t, u.external.arguments), 171804Svbart@nginx.com }, 172804Svbart@nginx.com 173804Svbart@nginx.com }; 174804Svbart@nginx.com 175804Svbart@nginx.com 176546Smax.romanov@nginx.com static nxt_conf_map_t nxt_python_app_conf[] = { 177271Smax.romanov@nginx.com { 178394Smax.romanov@nginx.com nxt_string("home"), 179394Smax.romanov@nginx.com NXT_CONF_MAP_CSTRZ, 180394Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.python.home), 181394Smax.romanov@nginx.com }, 182394Smax.romanov@nginx.com 183394Smax.romanov@nginx.com { 184240Sigor@sysoev.ru nxt_string("path"), 1851759Svbart@nginx.com NXT_CONF_MAP_PTR, 186240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, u.python.path), 187240Sigor@sysoev.ru }, 188240Sigor@sysoev.ru 189240Sigor@sysoev.ru { 190240Sigor@sysoev.ru nxt_string("module"), 191240Sigor@sysoev.ru NXT_CONF_MAP_STR, 192240Sigor@sysoev.ru offsetof(nxt_common_app_conf_t, u.python.module), 193240Sigor@sysoev.ru }, 1941601Smax.romanov@nginx.com 1951601Smax.romanov@nginx.com { 1961601Smax.romanov@nginx.com nxt_string("callable"), 1971601Smax.romanov@nginx.com NXT_CONF_MAP_CSTRZ, 1981601Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.python.callable), 1991601Smax.romanov@nginx.com }, 2001681Smax.romanov@nginx.com 2011681Smax.romanov@nginx.com { 2021697Smax.romanov@nginx.com nxt_string("protocol"), 2031697Smax.romanov@nginx.com NXT_CONF_MAP_STR, 2041697Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.python.protocol), 2051697Smax.romanov@nginx.com }, 2061697Smax.romanov@nginx.com 2071697Smax.romanov@nginx.com { 2081681Smax.romanov@nginx.com nxt_string("threads"), 2091681Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 2101681Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.python.threads), 2111681Smax.romanov@nginx.com }, 2121681Smax.romanov@nginx.com 2131681Smax.romanov@nginx.com { 2141872So.canty@f5.com nxt_string("targets"), 2151872So.canty@f5.com NXT_CONF_MAP_PTR, 2161872So.canty@f5.com offsetof(nxt_common_app_conf_t, u.python.targets), 2171872So.canty@f5.com }, 2181872So.canty@f5.com 2191872So.canty@f5.com { 2201681Smax.romanov@nginx.com nxt_string("thread_stack_size"), 2211681Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 2221681Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.python.thread_stack_size), 2231681Smax.romanov@nginx.com }, 224510Salexander.borisov@nginx.com }; 225240Sigor@sysoev.ru 226510Salexander.borisov@nginx.com 227546Smax.romanov@nginx.com static nxt_conf_map_t nxt_php_app_conf[] = { 228240Sigor@sysoev.ru { 2291473Svbart@nginx.com nxt_string("targets"), 2301473Svbart@nginx.com NXT_CONF_MAP_PTR, 2311473Svbart@nginx.com offsetof(nxt_common_app_conf_t, u.php.targets), 232240Sigor@sysoev.ru }, 233687Svbart@nginx.com 234687Svbart@nginx.com { 235687Svbart@nginx.com nxt_string("options"), 236687Svbart@nginx.com NXT_CONF_MAP_PTR, 237687Svbart@nginx.com offsetof(nxt_common_app_conf_t, u.php.options), 238687Svbart@nginx.com }, 239510Salexander.borisov@nginx.com }; 240240Sigor@sysoev.ru 241510Salexander.borisov@nginx.com 242546Smax.romanov@nginx.com static nxt_conf_map_t nxt_perl_app_conf[] = { 243510Salexander.borisov@nginx.com { 244510Salexander.borisov@nginx.com nxt_string("script"), 245510Salexander.borisov@nginx.com NXT_CONF_MAP_CSTRZ, 246510Salexander.borisov@nginx.com offsetof(nxt_common_app_conf_t, u.perl.script), 247510Salexander.borisov@nginx.com }, 2481689Smax.romanov@nginx.com 2491689Smax.romanov@nginx.com { 2501689Smax.romanov@nginx.com nxt_string("threads"), 2511689Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 2521689Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.perl.threads), 2531689Smax.romanov@nginx.com }, 2541689Smax.romanov@nginx.com 2551689Smax.romanov@nginx.com { 2561689Smax.romanov@nginx.com nxt_string("thread_stack_size"), 2571689Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 2581689Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.perl.thread_stack_size), 2591689Smax.romanov@nginx.com }, 260510Salexander.borisov@nginx.com }; 261510Salexander.borisov@nginx.com 262510Salexander.borisov@nginx.com 263584Salexander.borisov@nginx.com static nxt_conf_map_t nxt_ruby_app_conf[] = { 264584Salexander.borisov@nginx.com { 265584Salexander.borisov@nginx.com nxt_string("script"), 266584Salexander.borisov@nginx.com NXT_CONF_MAP_STR, 267584Salexander.borisov@nginx.com offsetof(nxt_common_app_conf_t, u.ruby.script), 268584Salexander.borisov@nginx.com }, 2691687Smax.romanov@nginx.com { 2701687Smax.romanov@nginx.com nxt_string("threads"), 2711687Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 2721687Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.ruby.threads), 2731687Smax.romanov@nginx.com }, 274*1910So.canty@f5.com { 275*1910So.canty@f5.com nxt_string("hooks"), 276*1910So.canty@f5.com NXT_CONF_MAP_STR, 277*1910So.canty@f5.com offsetof(nxt_common_app_conf_t, u.ruby.hooks), 278*1910So.canty@f5.com } 279584Salexander.borisov@nginx.com }; 280584Salexander.borisov@nginx.com 281584Salexander.borisov@nginx.com 282977Smax.romanov@gmail.com static nxt_conf_map_t nxt_java_app_conf[] = { 283977Smax.romanov@gmail.com { 284977Smax.romanov@gmail.com nxt_string("classpath"), 285977Smax.romanov@gmail.com NXT_CONF_MAP_PTR, 286977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.classpath), 287977Smax.romanov@gmail.com }, 288977Smax.romanov@gmail.com { 289977Smax.romanov@gmail.com nxt_string("webapp"), 290977Smax.romanov@gmail.com NXT_CONF_MAP_CSTRZ, 291977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.webapp), 292977Smax.romanov@gmail.com }, 293977Smax.romanov@gmail.com { 294977Smax.romanov@gmail.com nxt_string("options"), 295977Smax.romanov@gmail.com NXT_CONF_MAP_PTR, 296977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.options), 297977Smax.romanov@gmail.com }, 298977Smax.romanov@gmail.com { 299977Smax.romanov@gmail.com nxt_string("unit_jars"), 300977Smax.romanov@gmail.com NXT_CONF_MAP_CSTRZ, 301977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.unit_jars), 302977Smax.romanov@gmail.com }, 3031684Smax.romanov@nginx.com { 3041684Smax.romanov@nginx.com nxt_string("threads"), 3051684Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 3061684Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.java.threads), 3071684Smax.romanov@nginx.com }, 3081684Smax.romanov@nginx.com { 3091684Smax.romanov@nginx.com nxt_string("thread_stack_size"), 3101684Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 3111684Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.java.thread_stack_size), 3121684Smax.romanov@nginx.com }, 313977Smax.romanov@gmail.com 314977Smax.romanov@gmail.com }; 315977Smax.romanov@gmail.com 316977Smax.romanov@gmail.com 317546Smax.romanov@nginx.com static nxt_conf_app_map_t nxt_app_maps[] = { 318804Svbart@nginx.com { nxt_nitems(nxt_external_app_conf), nxt_external_app_conf }, 319804Svbart@nginx.com { nxt_nitems(nxt_python_app_conf), nxt_python_app_conf }, 320804Svbart@nginx.com { nxt_nitems(nxt_php_app_conf), nxt_php_app_conf }, 321804Svbart@nginx.com { nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf }, 322804Svbart@nginx.com { nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf }, 323977Smax.romanov@gmail.com { nxt_nitems(nxt_java_app_conf), nxt_java_app_conf }, 324510Salexander.borisov@nginx.com }; 325510Salexander.borisov@nginx.com 326510Salexander.borisov@nginx.com 327240Sigor@sysoev.ru static void 328240Sigor@sysoev.ru nxt_port_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 329240Sigor@sysoev.ru { 330240Sigor@sysoev.ru nxt_debug(task, "main data: %*s", 331240Sigor@sysoev.ru nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos); 332240Sigor@sysoev.ru } 333240Sigor@sysoev.ru 334240Sigor@sysoev.ru 335240Sigor@sysoev.ru static void 3361488St.nateldemoura@f5.com nxt_port_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 337240Sigor@sysoev.ru { 3381488St.nateldemoura@f5.com u_char *start, *p, ch; 339536Svbart@nginx.com size_t type_len; 340536Svbart@nginx.com nxt_int_t ret; 341240Sigor@sysoev.ru nxt_buf_t *b; 342318Smax.romanov@nginx.com nxt_port_t *port; 3431182St.nateldemoura@f5.com nxt_runtime_t *rt; 3441488St.nateldemoura@f5.com nxt_process_t *process; 345536Svbart@nginx.com nxt_app_type_t idx; 346240Sigor@sysoev.ru nxt_conf_value_t *conf; 3471488St.nateldemoura@f5.com nxt_process_init_t *init; 3481488St.nateldemoura@f5.com nxt_common_app_conf_t *app_conf; 349240Sigor@sysoev.ru 350318Smax.romanov@nginx.com ret = NXT_ERROR; 351318Smax.romanov@nginx.com 3521488St.nateldemoura@f5.com rt = task->thread->runtime; 353352Smax.romanov@nginx.com 3541488St.nateldemoura@f5.com process = nxt_main_process_new(task, rt); 3551488St.nateldemoura@f5.com if (nxt_slow_path(process == NULL)) { 356352Smax.romanov@nginx.com return; 357352Smax.romanov@nginx.com } 358352Smax.romanov@nginx.com 3591488St.nateldemoura@f5.com init = nxt_process_init(process); 3601488St.nateldemoura@f5.com 3611488St.nateldemoura@f5.com *init = nxt_app_process; 362352Smax.romanov@nginx.com 3631488St.nateldemoura@f5.com b = nxt_buf_chk_make_plain(process->mem_pool, msg->buf, msg->size); 364352Smax.romanov@nginx.com if (b == NULL) { 3651488St.nateldemoura@f5.com goto failed; 366352Smax.romanov@nginx.com } 367240Sigor@sysoev.ru 3681488St.nateldemoura@f5.com nxt_debug(task, "main start process: %*s", b->mem.free - b->mem.pos, 369240Sigor@sysoev.ru b->mem.pos); 370240Sigor@sysoev.ru 3711488St.nateldemoura@f5.com app_conf = nxt_mp_zalloc(process->mem_pool, sizeof(nxt_common_app_conf_t)); 3721488St.nateldemoura@f5.com if (nxt_slow_path(app_conf == NULL)) { 3731488St.nateldemoura@f5.com goto failed; 3741488St.nateldemoura@f5.com } 375240Sigor@sysoev.ru 376240Sigor@sysoev.ru start = b->mem.pos; 377240Sigor@sysoev.ru 3781488St.nateldemoura@f5.com app_conf->name.start = start; 3791488St.nateldemoura@f5.com app_conf->name.length = nxt_strlen(start); 3801488St.nateldemoura@f5.com 3811488St.nateldemoura@f5.com init->name = (const char *) start; 3821488St.nateldemoura@f5.com 3831488St.nateldemoura@f5.com process->name = nxt_mp_alloc(process->mem_pool, app_conf->name.length 3841488St.nateldemoura@f5.com + sizeof("\"\" application") + 1); 3851488St.nateldemoura@f5.com 3861488St.nateldemoura@f5.com if (nxt_slow_path(process->name == NULL)) { 3871488St.nateldemoura@f5.com goto failed; 3881488St.nateldemoura@f5.com } 389240Sigor@sysoev.ru 3901488St.nateldemoura@f5.com p = (u_char *) process->name; 3911488St.nateldemoura@f5.com *p++ = '"'; 3921488St.nateldemoura@f5.com p = nxt_cpymem(p, init->name, app_conf->name.length); 3931488St.nateldemoura@f5.com p = nxt_cpymem(p, "\" application", 13); 3941488St.nateldemoura@f5.com *p = '\0'; 395240Sigor@sysoev.ru 3961488St.nateldemoura@f5.com app_conf->shm_limit = 100 * 1024 * 1024; 397240Sigor@sysoev.ru 3981488St.nateldemoura@f5.com start += app_conf->name.length + 1; 3991488St.nateldemoura@f5.com 4001488St.nateldemoura@f5.com conf = nxt_conf_json_parse(process->mem_pool, start, b->mem.free, NULL); 401240Sigor@sysoev.ru if (conf == NULL) { 402564Svbart@nginx.com nxt_alert(task, "router app configuration parsing error"); 403318Smax.romanov@nginx.com 404318Smax.romanov@nginx.com goto failed; 405240Sigor@sysoev.ru } 406240Sigor@sysoev.ru 4071182St.nateldemoura@f5.com rt = task->thread->runtime; 4081182St.nateldemoura@f5.com 4091488St.nateldemoura@f5.com app_conf->user.start = (u_char*)rt->user_cred.user; 4101488St.nateldemoura@f5.com app_conf->user.length = nxt_strlen(rt->user_cred.user); 411240Sigor@sysoev.ru 4121488St.nateldemoura@f5.com ret = nxt_conf_map_object(process->mem_pool, conf, nxt_common_app_conf, 4131488St.nateldemoura@f5.com nxt_nitems(nxt_common_app_conf), app_conf); 4141488St.nateldemoura@f5.com 415240Sigor@sysoev.ru if (ret != NXT_OK) { 416564Svbart@nginx.com nxt_alert(task, "failed to map common app conf received from router"); 417318Smax.romanov@nginx.com goto failed; 418240Sigor@sysoev.ru } 419240Sigor@sysoev.ru 4201488St.nateldemoura@f5.com for (type_len = 0; type_len != app_conf->type.length; type_len++) { 4211488St.nateldemoura@f5.com ch = app_conf->type.start[type_len]; 422536Svbart@nginx.com 423536Svbart@nginx.com if (ch == ' ' || nxt_isdigit(ch)) { 424536Svbart@nginx.com break; 425536Svbart@nginx.com } 426536Svbart@nginx.com } 427536Svbart@nginx.com 4281488St.nateldemoura@f5.com idx = nxt_app_parse_type(app_conf->type.start, type_len); 429510Salexander.borisov@nginx.com 430546Smax.romanov@nginx.com if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) { 431564Svbart@nginx.com nxt_alert(task, "invalid app type %d received from router", (int) idx); 432546Smax.romanov@nginx.com goto failed; 433546Smax.romanov@nginx.com } 434510Salexander.borisov@nginx.com 4351488St.nateldemoura@f5.com ret = nxt_conf_map_object(process->mem_pool, conf, nxt_app_maps[idx].map, 4361488St.nateldemoura@f5.com nxt_app_maps[idx].size, app_conf); 437510Salexander.borisov@nginx.com 438546Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 439564Svbart@nginx.com nxt_alert(task, "failed to map app conf received from router"); 440546Smax.romanov@nginx.com goto failed; 441546Smax.romanov@nginx.com } 442510Salexander.borisov@nginx.com 4431488St.nateldemoura@f5.com if (app_conf->limits != NULL) { 4441488St.nateldemoura@f5.com ret = nxt_conf_map_object(process->mem_pool, app_conf->limits, 4451320Smax.romanov@nginx.com nxt_common_app_limits_conf, 4461320Smax.romanov@nginx.com nxt_nitems(nxt_common_app_limits_conf), 4471488St.nateldemoura@f5.com app_conf); 4481320Smax.romanov@nginx.com 4491320Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 4501320Smax.romanov@nginx.com nxt_alert(task, "failed to map app limits received from router"); 4511320Smax.romanov@nginx.com goto failed; 4521320Smax.romanov@nginx.com } 4531320Smax.romanov@nginx.com } 4541320Smax.romanov@nginx.com 4551488St.nateldemoura@f5.com app_conf->self = conf; 4561488St.nateldemoura@f5.com 4571488St.nateldemoura@f5.com process->stream = msg->port_msg.stream; 4581488St.nateldemoura@f5.com process->data.app = app_conf; 4591473Svbart@nginx.com 4601488St.nateldemoura@f5.com ret = nxt_main_start_process(task, process); 4611488St.nateldemoura@f5.com if (nxt_fast_path(ret == NXT_OK || ret == NXT_AGAIN)) { 4621488St.nateldemoura@f5.com return; 4631488St.nateldemoura@f5.com } 464240Sigor@sysoev.ru 465318Smax.romanov@nginx.com failed: 466318Smax.romanov@nginx.com 4671488St.nateldemoura@f5.com nxt_process_use(task, process, -1); 4681488St.nateldemoura@f5.com 4691488St.nateldemoura@f5.com port = nxt_runtime_port_find(rt, msg->port_msg.pid, 4701488St.nateldemoura@f5.com msg->port_msg.reply_port); 4711488St.nateldemoura@f5.com 4721488St.nateldemoura@f5.com if (nxt_fast_path(port != NULL)) { 4731488St.nateldemoura@f5.com nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, 4741488St.nateldemoura@f5.com -1, msg->port_msg.stream, 0, NULL); 4751488St.nateldemoura@f5.com } 4761488St.nateldemoura@f5.com } 4771488St.nateldemoura@f5.com 4781488St.nateldemoura@f5.com 4791488St.nateldemoura@f5.com static void 4801488St.nateldemoura@f5.com nxt_main_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 4811488St.nateldemoura@f5.com { 4821488St.nateldemoura@f5.com nxt_port_t *port; 4831488St.nateldemoura@f5.com nxt_process_t *process; 4841488St.nateldemoura@f5.com nxt_runtime_t *rt; 4851488St.nateldemoura@f5.com 4861488St.nateldemoura@f5.com rt = task->thread->runtime; 4871488St.nateldemoura@f5.com 4881488St.nateldemoura@f5.com process = nxt_runtime_process_find(rt, msg->port_msg.pid); 4891488St.nateldemoura@f5.com if (nxt_slow_path(process == NULL)) { 4901488St.nateldemoura@f5.com return; 491318Smax.romanov@nginx.com } 492318Smax.romanov@nginx.com 4931488St.nateldemoura@f5.com nxt_assert(process->state == NXT_PROCESS_STATE_CREATING); 4941488St.nateldemoura@f5.com 4951488St.nateldemoura@f5.com port = nxt_runtime_port_find(rt, msg->port_msg.pid, 4961488St.nateldemoura@f5.com msg->port_msg.reply_port); 4971488St.nateldemoura@f5.com 4981488St.nateldemoura@f5.com 4991488St.nateldemoura@f5.com if (nxt_slow_path(port == NULL)) { 5001488St.nateldemoura@f5.com return; 5011488St.nateldemoura@f5.com } 5021488St.nateldemoura@f5.com 5031488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER) 5041488St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { 5051488St.nateldemoura@f5.com if (nxt_slow_path(nxt_clone_credential_map(task, process->pid, 5061488St.nateldemoura@f5.com process->user_cred, 5071488St.nateldemoura@f5.com &process->isolation.clone) 5081488St.nateldemoura@f5.com != NXT_OK)) 5091488St.nateldemoura@f5.com { 5101488St.nateldemoura@f5.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, 5111488St.nateldemoura@f5.com -1, msg->port_msg.stream, 0, NULL); 5121488St.nateldemoura@f5.com return; 5131488St.nateldemoura@f5.com } 5141488St.nateldemoura@f5.com } 5151488St.nateldemoura@f5.com 5161488St.nateldemoura@f5.com #endif 5171488St.nateldemoura@f5.com 5181488St.nateldemoura@f5.com process->state = NXT_PROCESS_STATE_CREATED; 5191488St.nateldemoura@f5.com 5201488St.nateldemoura@f5.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST, 5211488St.nateldemoura@f5.com -1, msg->port_msg.stream, 0, NULL); 522240Sigor@sysoev.ru } 523240Sigor@sysoev.ru 524240Sigor@sysoev.ru 525320Smax.romanov@nginx.com static nxt_port_handlers_t nxt_main_process_port_handlers = { 5261488St.nateldemoura@f5.com .data = nxt_port_main_data_handler, 5271488St.nateldemoura@f5.com .process_created = nxt_main_process_created_handler, 5281488St.nateldemoura@f5.com .process_ready = nxt_port_process_ready_handler, 5291488St.nateldemoura@f5.com .start_process = nxt_port_main_start_process_handler, 5301488St.nateldemoura@f5.com .socket = nxt_main_port_socket_handler, 5311488St.nateldemoura@f5.com .modules = nxt_main_port_modules_handler, 5321488St.nateldemoura@f5.com .conf_store = nxt_main_port_conf_store_handler, 533774Svbart@nginx.com #if (NXT_TLS) 5341488St.nateldemoura@f5.com .cert_get = nxt_cert_store_get_handler, 5351488St.nateldemoura@f5.com .cert_delete = nxt_cert_store_delete_handler, 536774Svbart@nginx.com #endif 5371488St.nateldemoura@f5.com .access_log = nxt_main_port_access_log_handler, 5381488St.nateldemoura@f5.com .rpc_ready = nxt_port_rpc_handler, 5391488St.nateldemoura@f5.com .rpc_error = nxt_port_rpc_handler, 540240Sigor@sysoev.ru }; 541240Sigor@sysoev.ru 542240Sigor@sysoev.ru 543240Sigor@sysoev.ru static nxt_int_t 544240Sigor@sysoev.ru nxt_main_process_port_create(nxt_task_t *task, nxt_runtime_t *rt) 545240Sigor@sysoev.ru { 546240Sigor@sysoev.ru nxt_int_t ret; 547240Sigor@sysoev.ru nxt_port_t *port; 548240Sigor@sysoev.ru nxt_process_t *process; 549240Sigor@sysoev.ru 5501254Shongzhidao@gmail.com port = nxt_runtime_process_port_create(task, rt, nxt_pid, 0, 5511254Shongzhidao@gmail.com NXT_PROCESS_MAIN); 552240Sigor@sysoev.ru if (nxt_slow_path(port == NULL)) { 553240Sigor@sysoev.ru return NXT_ERROR; 554240Sigor@sysoev.ru } 555240Sigor@sysoev.ru 5561254Shongzhidao@gmail.com process = port->process; 557349Smax.romanov@nginx.com 558240Sigor@sysoev.ru ret = nxt_port_socket_init(task, port, 0); 559240Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 5601488St.nateldemoura@f5.com nxt_port_use(task, port, -1); 561240Sigor@sysoev.ru return ret; 562240Sigor@sysoev.ru } 563240Sigor@sysoev.ru 564240Sigor@sysoev.ru /* 565240Sigor@sysoev.ru * A main process port. A write port is not closed 5661488St.nateldemoura@f5.com * since it should be inherited by processes. 567240Sigor@sysoev.ru */ 568320Smax.romanov@nginx.com nxt_port_enable(task, port, &nxt_main_process_port_handlers); 569240Sigor@sysoev.ru 5701488St.nateldemoura@f5.com process->state = NXT_PROCESS_STATE_READY; 571240Sigor@sysoev.ru 572240Sigor@sysoev.ru return NXT_OK; 573240Sigor@sysoev.ru } 574240Sigor@sysoev.ru 575240Sigor@sysoev.ru 576240Sigor@sysoev.ru static void 577240Sigor@sysoev.ru nxt_main_process_title(nxt_task_t *task) 578240Sigor@sysoev.ru { 579240Sigor@sysoev.ru u_char *p, *end; 580240Sigor@sysoev.ru nxt_uint_t i; 581240Sigor@sysoev.ru u_char title[2048]; 582240Sigor@sysoev.ru 583240Sigor@sysoev.ru end = title + sizeof(title) - 1; 584240Sigor@sysoev.ru 585680Sigor@sysoev.ru p = nxt_sprintf(title, end, "unit: main v" NXT_VERSION " [%s", 586680Sigor@sysoev.ru nxt_process_argv[0]); 587240Sigor@sysoev.ru 588240Sigor@sysoev.ru for (i = 1; nxt_process_argv[i] != NULL; i++) { 589240Sigor@sysoev.ru p = nxt_sprintf(p, end, " %s", nxt_process_argv[i]); 590240Sigor@sysoev.ru } 591240Sigor@sysoev.ru 592240Sigor@sysoev.ru if (p < end) { 593240Sigor@sysoev.ru *p++ = ']'; 594240Sigor@sysoev.ru } 595240Sigor@sysoev.ru 596240Sigor@sysoev.ru *p = '\0'; 597240Sigor@sysoev.ru 598240Sigor@sysoev.ru nxt_process_title(task, "%s", title); 599240Sigor@sysoev.ru } 600240Sigor@sysoev.ru 601240Sigor@sysoev.ru 602240Sigor@sysoev.ru static nxt_int_t 6031488St.nateldemoura@f5.com nxt_main_process_create(nxt_task_t *task, const nxt_process_init_t init) 604240Sigor@sysoev.ru { 6051488St.nateldemoura@f5.com nxt_int_t ret; 6061488St.nateldemoura@f5.com nxt_runtime_t *rt; 6071488St.nateldemoura@f5.com nxt_process_t *process; 6081488St.nateldemoura@f5.com nxt_process_init_t *pinit; 609240Sigor@sysoev.ru 6101488St.nateldemoura@f5.com rt = task->thread->runtime; 6111302St.nateldemoura@f5.com 6121488St.nateldemoura@f5.com process = nxt_main_process_new(task, rt); 6131488St.nateldemoura@f5.com if (nxt_slow_path(process == NULL)) { 614368Svbart@nginx.com return NXT_ERROR; 615368Svbart@nginx.com } 616368Svbart@nginx.com 6171488St.nateldemoura@f5.com process->name = init.name; 6181488St.nateldemoura@f5.com process->user_cred = &rt->user_cred; 619314Svbart@nginx.com 6201488St.nateldemoura@f5.com pinit = nxt_process_init(process); 6211488St.nateldemoura@f5.com *pinit = init; 622314Svbart@nginx.com 6231488St.nateldemoura@f5.com ret = nxt_main_start_process(task, process); 6241488St.nateldemoura@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 6251488St.nateldemoura@f5.com nxt_process_use(task, process, -1); 626314Svbart@nginx.com } 627314Svbart@nginx.com 628314Svbart@nginx.com return ret; 629240Sigor@sysoev.ru } 630240Sigor@sysoev.ru 631240Sigor@sysoev.ru 6321488St.nateldemoura@f5.com static nxt_process_t * 6331488St.nateldemoura@f5.com nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt) 634240Sigor@sysoev.ru { 6351488St.nateldemoura@f5.com nxt_process_t *process; 636240Sigor@sysoev.ru 6371488St.nateldemoura@f5.com process = nxt_runtime_process_new(rt); 6381488St.nateldemoura@f5.com if (nxt_slow_path(process == NULL)) { 6391488St.nateldemoura@f5.com return NULL; 640240Sigor@sysoev.ru } 641240Sigor@sysoev.ru 6421488St.nateldemoura@f5.com process->mem_pool = nxt_mp_create(1024, 128, 256, 32); 6431488St.nateldemoura@f5.com if (process->mem_pool == NULL) { 6441488St.nateldemoura@f5.com nxt_process_use(task, process, -1); 6451488St.nateldemoura@f5.com return NULL; 646240Sigor@sysoev.ru } 647240Sigor@sysoev.ru 6481488St.nateldemoura@f5.com return process; 649240Sigor@sysoev.ru } 650240Sigor@sysoev.ru 6511302St.nateldemoura@f5.com 652240Sigor@sysoev.ru static nxt_int_t 6531488St.nateldemoura@f5.com nxt_main_start_process(nxt_task_t *task, nxt_process_t *process) 654240Sigor@sysoev.ru { 6551488St.nateldemoura@f5.com nxt_mp_t *tmp_mp; 6561182St.nateldemoura@f5.com nxt_int_t ret; 6571488St.nateldemoura@f5.com nxt_pid_t pid; 6581488St.nateldemoura@f5.com nxt_port_t *port; 659240Sigor@sysoev.ru nxt_process_init_t *init; 660240Sigor@sysoev.ru 6611488St.nateldemoura@f5.com init = nxt_process_init(process); 662240Sigor@sysoev.ru 663240Sigor@sysoev.ru port = nxt_port_new(task, 0, 0, init->type); 664240Sigor@sysoev.ru if (nxt_slow_path(port == NULL)) { 665240Sigor@sysoev.ru return NXT_ERROR; 666240Sigor@sysoev.ru } 667240Sigor@sysoev.ru 668240Sigor@sysoev.ru nxt_process_port_add(task, process, port); 669240Sigor@sysoev.ru 670240Sigor@sysoev.ru ret = nxt_port_socket_init(task, port, 0); 671240Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 6721565St.nateldemoura@f5.com goto free_port; 6731488St.nateldemoura@f5.com } 6741488St.nateldemoura@f5.com 6751488St.nateldemoura@f5.com tmp_mp = nxt_mp_create(1024, 128, 256, 32); 6761565St.nateldemoura@f5.com if (nxt_slow_path(tmp_mp == NULL)) { 6771565St.nateldemoura@f5.com ret = NXT_ERROR; 6781565St.nateldemoura@f5.com 6791565St.nateldemoura@f5.com goto close_port; 6801488St.nateldemoura@f5.com } 6811488St.nateldemoura@f5.com 6821488St.nateldemoura@f5.com if (init->prefork) { 6831488St.nateldemoura@f5.com ret = init->prefork(task, process, tmp_mp); 6841488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 6851565St.nateldemoura@f5.com goto free_mempool; 6861488St.nateldemoura@f5.com } 687240Sigor@sysoev.ru } 688240Sigor@sysoev.ru 689240Sigor@sysoev.ru pid = nxt_process_create(task, process); 690240Sigor@sysoev.ru 691240Sigor@sysoev.ru switch (pid) { 692240Sigor@sysoev.ru 693240Sigor@sysoev.ru case -1: 6941565St.nateldemoura@f5.com ret = NXT_ERROR; 6951488St.nateldemoura@f5.com break; 696240Sigor@sysoev.ru 697240Sigor@sysoev.ru case 0: 6981488St.nateldemoura@f5.com /* The child process: return to the event engine work queue loop. */ 6991180Smax.romanov@nginx.com 7001565St.nateldemoura@f5.com nxt_process_use(task, process, -1); 7011565St.nateldemoura@f5.com 7021488St.nateldemoura@f5.com ret = NXT_AGAIN; 7031488St.nateldemoura@f5.com break; 704240Sigor@sysoev.ru 705240Sigor@sysoev.ru default: 706240Sigor@sysoev.ru /* The main process created a new process. */ 707240Sigor@sysoev.ru 7081565St.nateldemoura@f5.com nxt_process_use(task, process, -1); 7091565St.nateldemoura@f5.com 710240Sigor@sysoev.ru nxt_port_read_close(port); 711240Sigor@sysoev.ru nxt_port_write_enable(task, port); 712240Sigor@sysoev.ru 7131488St.nateldemoura@f5.com ret = NXT_OK; 7141488St.nateldemoura@f5.com break; 715240Sigor@sysoev.ru } 716240Sigor@sysoev.ru 7171565St.nateldemoura@f5.com free_mempool: 7181565St.nateldemoura@f5.com 7191565St.nateldemoura@f5.com nxt_mp_destroy(tmp_mp); 7201565St.nateldemoura@f5.com 7211565St.nateldemoura@f5.com close_port: 7221565St.nateldemoura@f5.com 7231565St.nateldemoura@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 7241565St.nateldemoura@f5.com nxt_port_close(task, port); 7251565St.nateldemoura@f5.com } 7261565St.nateldemoura@f5.com 7271565St.nateldemoura@f5.com free_port: 728240Sigor@sysoev.ru 7291488St.nateldemoura@f5.com nxt_port_use(task, port, -1); 730240Sigor@sysoev.ru 7311488St.nateldemoura@f5.com return ret; 732240Sigor@sysoev.ru } 733240Sigor@sysoev.ru 734240Sigor@sysoev.ru 735240Sigor@sysoev.ru static void 736240Sigor@sysoev.ru nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, void *data) 737240Sigor@sysoev.ru { 738240Sigor@sysoev.ru nxt_debug(task, "sigterm handler signo:%d (%s)", 739240Sigor@sysoev.ru (int) (uintptr_t) obj, data); 740240Sigor@sysoev.ru 741240Sigor@sysoev.ru /* TODO: fast exit. */ 742240Sigor@sysoev.ru 743240Sigor@sysoev.ru nxt_exiting = 1; 744240Sigor@sysoev.ru 745697Sigor@sysoev.ru nxt_runtime_quit(task, 0); 746240Sigor@sysoev.ru } 747240Sigor@sysoev.ru 748240Sigor@sysoev.ru 749240Sigor@sysoev.ru static void 750240Sigor@sysoev.ru nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, void *data) 751240Sigor@sysoev.ru { 752240Sigor@sysoev.ru nxt_debug(task, "sigquit handler signo:%d (%s)", 753240Sigor@sysoev.ru (int) (uintptr_t) obj, data); 754240Sigor@sysoev.ru 755240Sigor@sysoev.ru /* TODO: graceful exit. */ 756240Sigor@sysoev.ru 757240Sigor@sysoev.ru nxt_exiting = 1; 758240Sigor@sysoev.ru 759697Sigor@sysoev.ru nxt_runtime_quit(task, 0); 760240Sigor@sysoev.ru } 761240Sigor@sysoev.ru 762240Sigor@sysoev.ru 763240Sigor@sysoev.ru static void 764240Sigor@sysoev.ru nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, void *data) 765240Sigor@sysoev.ru { 766240Sigor@sysoev.ru nxt_mp_t *mp; 767240Sigor@sysoev.ru nxt_int_t ret; 768240Sigor@sysoev.ru nxt_uint_t n; 769631Svbart@nginx.com nxt_port_t *port; 770240Sigor@sysoev.ru nxt_file_t *file, *new_file; 771631Svbart@nginx.com nxt_array_t *new_files; 772240Sigor@sysoev.ru nxt_runtime_t *rt; 773240Sigor@sysoev.ru 774240Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "signal %d (%s) recevied, %s", 775240Sigor@sysoev.ru (int) (uintptr_t) obj, data, "log files rotation"); 776240Sigor@sysoev.ru 777631Svbart@nginx.com rt = task->thread->runtime; 778631Svbart@nginx.com 779631Svbart@nginx.com port = rt->port_by_type[NXT_PROCESS_ROUTER]; 780631Svbart@nginx.com 781631Svbart@nginx.com if (nxt_fast_path(port != NULL)) { 782631Svbart@nginx.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_ACCESS_LOG, 783631Svbart@nginx.com -1, 0, 0, NULL); 784631Svbart@nginx.com } 785631Svbart@nginx.com 786240Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 787240Sigor@sysoev.ru if (mp == NULL) { 788240Sigor@sysoev.ru return; 789240Sigor@sysoev.ru } 790240Sigor@sysoev.ru 791240Sigor@sysoev.ru n = nxt_list_nelts(rt->log_files); 792240Sigor@sysoev.ru 793240Sigor@sysoev.ru new_files = nxt_array_create(mp, n, sizeof(nxt_file_t)); 794240Sigor@sysoev.ru if (new_files == NULL) { 795240Sigor@sysoev.ru nxt_mp_destroy(mp); 796240Sigor@sysoev.ru return; 797240Sigor@sysoev.ru } 798240Sigor@sysoev.ru 799240Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 800240Sigor@sysoev.ru 801240Sigor@sysoev.ru /* This allocation cannot fail. */ 802240Sigor@sysoev.ru new_file = nxt_array_add(new_files); 803240Sigor@sysoev.ru 804240Sigor@sysoev.ru new_file->name = file->name; 805240Sigor@sysoev.ru new_file->fd = NXT_FILE_INVALID; 806564Svbart@nginx.com new_file->log_level = NXT_LOG_ALERT; 807240Sigor@sysoev.ru 808240Sigor@sysoev.ru ret = nxt_file_open(task, new_file, O_WRONLY | O_APPEND, O_CREAT, 809240Sigor@sysoev.ru NXT_FILE_OWNER_ACCESS); 810240Sigor@sysoev.ru 811240Sigor@sysoev.ru if (ret != NXT_OK) { 812240Sigor@sysoev.ru goto fail; 813240Sigor@sysoev.ru } 814240Sigor@sysoev.ru 815240Sigor@sysoev.ru } nxt_list_loop; 816240Sigor@sysoev.ru 817240Sigor@sysoev.ru new_file = new_files->elts; 818240Sigor@sysoev.ru 819240Sigor@sysoev.ru ret = nxt_file_stderr(&new_file[0]); 820240Sigor@sysoev.ru 821240Sigor@sysoev.ru if (ret == NXT_OK) { 822240Sigor@sysoev.ru n = 0; 823240Sigor@sysoev.ru 824240Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 825240Sigor@sysoev.ru 826240Sigor@sysoev.ru nxt_port_change_log_file(task, rt, n, new_file[n].fd); 827240Sigor@sysoev.ru /* 828240Sigor@sysoev.ru * The old log file descriptor must be closed at the moment 829240Sigor@sysoev.ru * when no other threads use it. dup2() allows to use the 830240Sigor@sysoev.ru * old file descriptor for new log file. This change is 831240Sigor@sysoev.ru * performed atomically in the kernel. 832240Sigor@sysoev.ru */ 833240Sigor@sysoev.ru (void) nxt_file_redirect(file, new_file[n].fd); 834240Sigor@sysoev.ru 835240Sigor@sysoev.ru n++; 836240Sigor@sysoev.ru 837240Sigor@sysoev.ru } nxt_list_loop; 838240Sigor@sysoev.ru 839240Sigor@sysoev.ru nxt_mp_destroy(mp); 840240Sigor@sysoev.ru return; 8411008Szelenkov@nginx.com } 842240Sigor@sysoev.ru 843240Sigor@sysoev.ru fail: 844240Sigor@sysoev.ru 845240Sigor@sysoev.ru new_file = new_files->elts; 846240Sigor@sysoev.ru n = new_files->nelts; 847240Sigor@sysoev.ru 848240Sigor@sysoev.ru while (n != 0) { 849240Sigor@sysoev.ru if (new_file->fd != NXT_FILE_INVALID) { 850240Sigor@sysoev.ru nxt_file_close(task, new_file); 851240Sigor@sysoev.ru } 852240Sigor@sysoev.ru 853240Sigor@sysoev.ru new_file++; 854240Sigor@sysoev.ru n--; 855240Sigor@sysoev.ru } 856240Sigor@sysoev.ru 857240Sigor@sysoev.ru nxt_mp_destroy(mp); 858240Sigor@sysoev.ru } 859240Sigor@sysoev.ru 860240Sigor@sysoev.ru 861240Sigor@sysoev.ru static void 862240Sigor@sysoev.ru nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, void *data) 863240Sigor@sysoev.ru { 864240Sigor@sysoev.ru int status; 865240Sigor@sysoev.ru nxt_err_t err; 866240Sigor@sysoev.ru nxt_pid_t pid; 867240Sigor@sysoev.ru 868240Sigor@sysoev.ru nxt_debug(task, "sigchld handler signo:%d (%s)", 869240Sigor@sysoev.ru (int) (uintptr_t) obj, data); 870240Sigor@sysoev.ru 871240Sigor@sysoev.ru for ( ;; ) { 872240Sigor@sysoev.ru pid = waitpid(-1, &status, WNOHANG); 873240Sigor@sysoev.ru 874240Sigor@sysoev.ru if (pid == -1) { 875240Sigor@sysoev.ru 876240Sigor@sysoev.ru switch (err = nxt_errno) { 877240Sigor@sysoev.ru 878240Sigor@sysoev.ru case NXT_ECHILD: 879240Sigor@sysoev.ru return; 880240Sigor@sysoev.ru 881240Sigor@sysoev.ru case NXT_EINTR: 882240Sigor@sysoev.ru continue; 883240Sigor@sysoev.ru 884240Sigor@sysoev.ru default: 885564Svbart@nginx.com nxt_alert(task, "waitpid() failed: %E", err); 886240Sigor@sysoev.ru return; 887240Sigor@sysoev.ru } 888240Sigor@sysoev.ru } 889240Sigor@sysoev.ru 890240Sigor@sysoev.ru nxt_debug(task, "waitpid(): %PI", pid); 891240Sigor@sysoev.ru 892240Sigor@sysoev.ru if (pid == 0) { 893240Sigor@sysoev.ru return; 894240Sigor@sysoev.ru } 895240Sigor@sysoev.ru 896240Sigor@sysoev.ru if (WTERMSIG(status)) { 897240Sigor@sysoev.ru #ifdef WCOREDUMP 898564Svbart@nginx.com nxt_alert(task, "process %PI exited on signal %d%s", 899564Svbart@nginx.com pid, WTERMSIG(status), 900564Svbart@nginx.com WCOREDUMP(status) ? " (core dumped)" : ""); 901240Sigor@sysoev.ru #else 902564Svbart@nginx.com nxt_alert(task, "process %PI exited on signal %d", 903564Svbart@nginx.com pid, WTERMSIG(status)); 904240Sigor@sysoev.ru #endif 905240Sigor@sysoev.ru 906240Sigor@sysoev.ru } else { 907240Sigor@sysoev.ru nxt_trace(task, "process %PI exited with code %d", 908240Sigor@sysoev.ru pid, WEXITSTATUS(status)); 909240Sigor@sysoev.ru } 910240Sigor@sysoev.ru 9111488St.nateldemoura@f5.com nxt_main_cleanup_process(task, pid); 912240Sigor@sysoev.ru } 913240Sigor@sysoev.ru } 914240Sigor@sysoev.ru 915240Sigor@sysoev.ru 916240Sigor@sysoev.ru static void 917944Sigor@sysoev.ru nxt_main_process_signal_handler(nxt_task_t *task, void *obj, void *data) 918944Sigor@sysoev.ru { 919944Sigor@sysoev.ru nxt_trace(task, "signal signo:%d (%s) recevied, ignored", 920944Sigor@sysoev.ru (int) (uintptr_t) obj, data); 921944Sigor@sysoev.ru } 922944Sigor@sysoev.ru 923944Sigor@sysoev.ru 924944Sigor@sysoev.ru static void 9251488St.nateldemoura@f5.com nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid) 926240Sigor@sysoev.ru { 9271488St.nateldemoura@f5.com int stream; 9281488St.nateldemoura@f5.com nxt_int_t ret; 9291488St.nateldemoura@f5.com nxt_buf_t *buf; 9301488St.nateldemoura@f5.com nxt_port_t *port; 9311488St.nateldemoura@f5.com const char *name; 9321488St.nateldemoura@f5.com nxt_runtime_t *rt; 9331488St.nateldemoura@f5.com nxt_process_t *process; 9341488St.nateldemoura@f5.com nxt_process_init_t init; 935240Sigor@sysoev.ru 936240Sigor@sysoev.ru rt = task->thread->runtime; 937240Sigor@sysoev.ru 938240Sigor@sysoev.ru process = nxt_runtime_process_find(rt, pid); 9391488St.nateldemoura@f5.com if (!process) { 9401488St.nateldemoura@f5.com return; 9411488St.nateldemoura@f5.com } 942240Sigor@sysoev.ru 9431579St.nateldemoura@f5.com if (process->isolation.cleanup != NULL) { 9441579St.nateldemoura@f5.com process->isolation.cleanup(task, process); 9451489St.nateldemoura@f5.com } 9461489St.nateldemoura@f5.com 9471488St.nateldemoura@f5.com name = process->name; 9481488St.nateldemoura@f5.com stream = process->stream; 9491488St.nateldemoura@f5.com init = *((nxt_process_init_t *) nxt_process_init(process)); 950366Smax.romanov@nginx.com 9511488St.nateldemoura@f5.com if (process->state == NXT_PROCESS_STATE_READY) { 9521488St.nateldemoura@f5.com process->stream = 0; 9531488St.nateldemoura@f5.com } 954240Sigor@sysoev.ru 9551488St.nateldemoura@f5.com nxt_process_close_ports(task, process); 9561302St.nateldemoura@f5.com 9571488St.nateldemoura@f5.com if (nxt_exiting) { 9581488St.nateldemoura@f5.com if (rt->nprocesses <= 1) { 9591488St.nateldemoura@f5.com nxt_runtime_quit(task, 0); 9601211Smax.romanov@nginx.com } 9611211Smax.romanov@nginx.com 9621488St.nateldemoura@f5.com return; 963240Sigor@sysoev.ru } 964754Smax.romanov@nginx.com 965754Smax.romanov@nginx.com nxt_runtime_process_each(rt, process) { 966754Smax.romanov@nginx.com 9671488St.nateldemoura@f5.com if (process->pid == nxt_pid 9681488St.nateldemoura@f5.com || process->pid == pid 9691488St.nateldemoura@f5.com || nxt_queue_is_empty(&process->ports)) 9701488St.nateldemoura@f5.com { 9711488St.nateldemoura@f5.com continue; 9721488St.nateldemoura@f5.com } 9731488St.nateldemoura@f5.com 9741488St.nateldemoura@f5.com port = nxt_process_port_first(process); 975754Smax.romanov@nginx.com 9761488St.nateldemoura@f5.com if (nxt_proc_remove_notify_matrix[init.type][port->type] == 0) { 9771488St.nateldemoura@f5.com continue; 9781488St.nateldemoura@f5.com } 9791488St.nateldemoura@f5.com 9801488St.nateldemoura@f5.com buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 9811488St.nateldemoura@f5.com sizeof(pid)); 982754Smax.romanov@nginx.com 9831488St.nateldemoura@f5.com if (nxt_slow_path(buf == NULL)) { 9841488St.nateldemoura@f5.com continue; 9851488St.nateldemoura@f5.com } 9861488St.nateldemoura@f5.com 9871488St.nateldemoura@f5.com buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid)); 9881488St.nateldemoura@f5.com 9891488St.nateldemoura@f5.com nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID, -1, 9901488St.nateldemoura@f5.com stream, 0, buf); 991754Smax.romanov@nginx.com 992754Smax.romanov@nginx.com } nxt_runtime_process_loop; 9931488St.nateldemoura@f5.com 9941488St.nateldemoura@f5.com if (init.restart) { 9951488St.nateldemoura@f5.com ret = nxt_main_process_create(task, init); 9961488St.nateldemoura@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 9971488St.nateldemoura@f5.com nxt_alert(task, "failed to restart %s", name); 9981488St.nateldemoura@f5.com } 9991488St.nateldemoura@f5.com } 1000754Smax.romanov@nginx.com } 1001754Smax.romanov@nginx.com 1002754Smax.romanov@nginx.com 1003754Smax.romanov@nginx.com static void 1004240Sigor@sysoev.ru nxt_main_port_socket_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1005240Sigor@sysoev.ru { 1006240Sigor@sysoev.ru size_t size; 1007240Sigor@sysoev.ru nxt_int_t ret; 1008240Sigor@sysoev.ru nxt_buf_t *b, *out; 1009240Sigor@sysoev.ru nxt_port_t *port; 1010240Sigor@sysoev.ru nxt_sockaddr_t *sa; 1011240Sigor@sysoev.ru nxt_port_msg_type_t type; 1012240Sigor@sysoev.ru nxt_listening_socket_t ls; 1013240Sigor@sysoev.ru u_char message[2048]; 1014240Sigor@sysoev.ru 10151788Smax.romanov@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 10161788Smax.romanov@nginx.com msg->port_msg.reply_port); 10171788Smax.romanov@nginx.com if (nxt_slow_path(port == NULL)) { 10181788Smax.romanov@nginx.com return; 10191788Smax.romanov@nginx.com } 10201788Smax.romanov@nginx.com 1021240Sigor@sysoev.ru b = msg->buf; 1022240Sigor@sysoev.ru sa = (nxt_sockaddr_t *) b->mem.pos; 1023240Sigor@sysoev.ru 1024352Smax.romanov@nginx.com /* TODO check b size and make plain */ 1025352Smax.romanov@nginx.com 1026240Sigor@sysoev.ru ls.socket = -1; 1027240Sigor@sysoev.ru ls.error = NXT_SOCKET_ERROR_SYSTEM; 1028240Sigor@sysoev.ru ls.start = message; 1029240Sigor@sysoev.ru ls.end = message + sizeof(message); 1030240Sigor@sysoev.ru 1031240Sigor@sysoev.ru nxt_debug(task, "listening socket \"%*s\"", 1032493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa)); 1033240Sigor@sysoev.ru 1034240Sigor@sysoev.ru ret = nxt_main_listening_socket(sa, &ls); 1035240Sigor@sysoev.ru 1036240Sigor@sysoev.ru if (ret == NXT_OK) { 1037240Sigor@sysoev.ru nxt_debug(task, "socket(\"%*s\"): %d", 1038493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), ls.socket); 1039240Sigor@sysoev.ru 10401788Smax.romanov@nginx.com out = NULL; 10411788Smax.romanov@nginx.com 1042240Sigor@sysoev.ru type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD; 1043240Sigor@sysoev.ru 1044240Sigor@sysoev.ru } else { 1045240Sigor@sysoev.ru size = ls.end - ls.start; 1046240Sigor@sysoev.ru 1047564Svbart@nginx.com nxt_alert(task, "%*s", size, ls.start); 1048240Sigor@sysoev.ru 1049342Smax.romanov@nginx.com out = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 1050342Smax.romanov@nginx.com size + 1); 10511788Smax.romanov@nginx.com if (nxt_fast_path(out != NULL)) { 10521788Smax.romanov@nginx.com *out->mem.free++ = (uint8_t) ls.error; 1053240Sigor@sysoev.ru 10541788Smax.romanov@nginx.com out->mem.free = nxt_cpymem(out->mem.free, ls.start, size); 10551788Smax.romanov@nginx.com } 1056240Sigor@sysoev.ru 1057240Sigor@sysoev.ru type = NXT_PORT_MSG_RPC_ERROR; 1058240Sigor@sysoev.ru } 1059240Sigor@sysoev.ru 1060240Sigor@sysoev.ru nxt_port_socket_write(task, port, type, ls.socket, msg->port_msg.stream, 1061240Sigor@sysoev.ru 0, out); 1062240Sigor@sysoev.ru } 1063240Sigor@sysoev.ru 1064240Sigor@sysoev.ru 1065240Sigor@sysoev.ru static nxt_int_t 1066240Sigor@sysoev.ru nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls) 1067240Sigor@sysoev.ru { 1068240Sigor@sysoev.ru nxt_err_t err; 1069240Sigor@sysoev.ru nxt_socket_t s; 1070240Sigor@sysoev.ru 1071240Sigor@sysoev.ru const socklen_t length = sizeof(int); 1072240Sigor@sysoev.ru static const int enable = 1; 1073240Sigor@sysoev.ru 1074240Sigor@sysoev.ru s = socket(sa->u.sockaddr.sa_family, sa->type, 0); 1075240Sigor@sysoev.ru 1076240Sigor@sysoev.ru if (nxt_slow_path(s == -1)) { 1077240Sigor@sysoev.ru err = nxt_errno; 1078240Sigor@sysoev.ru 1079240Sigor@sysoev.ru #if (NXT_INET6) 1080240Sigor@sysoev.ru 1081240Sigor@sysoev.ru if (err == EAFNOSUPPORT && sa->u.sockaddr.sa_family == AF_INET6) { 1082240Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_NOINET6; 1083240Sigor@sysoev.ru } 1084240Sigor@sysoev.ru 1085240Sigor@sysoev.ru #endif 1086240Sigor@sysoev.ru 1087240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1088240Sigor@sysoev.ru "socket(\\\"%*s\\\") failed %E", 1089493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), err); 1090240Sigor@sysoev.ru 1091240Sigor@sysoev.ru return NXT_ERROR; 1092240Sigor@sysoev.ru } 1093240Sigor@sysoev.ru 1094240Sigor@sysoev.ru if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, length) != 0) { 1095240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1096240Sigor@sysoev.ru "setsockopt(\\\"%*s\\\", SO_REUSEADDR) failed %E", 1097493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), 1098493Spluknet@nginx.com nxt_errno); 1099240Sigor@sysoev.ru goto fail; 1100240Sigor@sysoev.ru } 1101240Sigor@sysoev.ru 1102240Sigor@sysoev.ru #if (NXT_INET6) 1103240Sigor@sysoev.ru 1104240Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_INET6) { 1105240Sigor@sysoev.ru 1106240Sigor@sysoev.ru if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, length) != 0) { 1107240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1108240Sigor@sysoev.ru "setsockopt(\\\"%*s\\\", IPV6_V6ONLY) failed %E", 1109493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), 1110493Spluknet@nginx.com nxt_errno); 1111240Sigor@sysoev.ru goto fail; 1112240Sigor@sysoev.ru } 1113240Sigor@sysoev.ru } 1114240Sigor@sysoev.ru 1115240Sigor@sysoev.ru #endif 1116240Sigor@sysoev.ru 1117240Sigor@sysoev.ru if (bind(s, &sa->u.sockaddr, sa->socklen) != 0) { 1118240Sigor@sysoev.ru err = nxt_errno; 1119240Sigor@sysoev.ru 1120240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 1121240Sigor@sysoev.ru 1122240Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_UNIX) { 1123240Sigor@sysoev.ru switch (err) { 1124240Sigor@sysoev.ru 1125240Sigor@sysoev.ru case EACCES: 1126240Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_ACCESS; 1127240Sigor@sysoev.ru break; 1128240Sigor@sysoev.ru 1129240Sigor@sysoev.ru case ENOENT: 1130240Sigor@sysoev.ru case ENOTDIR: 1131240Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_PATH; 1132240Sigor@sysoev.ru break; 1133240Sigor@sysoev.ru } 1134240Sigor@sysoev.ru 1135908Sigor@sysoev.ru } else 1136908Sigor@sysoev.ru #endif 1137908Sigor@sysoev.ru { 1138908Sigor@sysoev.ru switch (err) { 1139240Sigor@sysoev.ru 1140908Sigor@sysoev.ru case EACCES: 1141908Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_PORT; 1142908Sigor@sysoev.ru break; 1143240Sigor@sysoev.ru 1144908Sigor@sysoev.ru case EADDRINUSE: 1145908Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_INUSE; 1146908Sigor@sysoev.ru break; 1147240Sigor@sysoev.ru 1148908Sigor@sysoev.ru case EADDRNOTAVAIL: 1149908Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_NOADDR; 1150908Sigor@sysoev.ru break; 1151908Sigor@sysoev.ru } 1152240Sigor@sysoev.ru } 1153240Sigor@sysoev.ru 1154240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, "bind(\\\"%*s\\\") failed %E", 1155493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), err); 1156240Sigor@sysoev.ru goto fail; 1157240Sigor@sysoev.ru } 1158240Sigor@sysoev.ru 1159240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 1160240Sigor@sysoev.ru 1161240Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_UNIX) { 1162240Sigor@sysoev.ru char *filename; 1163240Sigor@sysoev.ru mode_t access; 1164240Sigor@sysoev.ru 1165240Sigor@sysoev.ru filename = sa->u.sockaddr_un.sun_path; 1166240Sigor@sysoev.ru access = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 1167240Sigor@sysoev.ru 1168240Sigor@sysoev.ru if (chmod(filename, access) != 0) { 1169240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1170494Spluknet@nginx.com "chmod(\\\"%s\\\") failed %E", 1171240Sigor@sysoev.ru filename, nxt_errno); 1172240Sigor@sysoev.ru goto fail; 1173240Sigor@sysoev.ru } 1174240Sigor@sysoev.ru } 1175240Sigor@sysoev.ru 1176240Sigor@sysoev.ru #endif 1177240Sigor@sysoev.ru 1178240Sigor@sysoev.ru ls->socket = s; 1179240Sigor@sysoev.ru 1180240Sigor@sysoev.ru return NXT_OK; 1181240Sigor@sysoev.ru 1182240Sigor@sysoev.ru fail: 1183240Sigor@sysoev.ru 1184240Sigor@sysoev.ru (void) close(s); 1185240Sigor@sysoev.ru 1186240Sigor@sysoev.ru return NXT_ERROR; 1187240Sigor@sysoev.ru } 1188240Sigor@sysoev.ru 1189240Sigor@sysoev.ru 1190240Sigor@sysoev.ru static nxt_conf_map_t nxt_app_lang_module_map[] = { 1191240Sigor@sysoev.ru { 1192240Sigor@sysoev.ru nxt_string("type"), 1193356Svbart@nginx.com NXT_CONF_MAP_INT, 1194240Sigor@sysoev.ru offsetof(nxt_app_lang_module_t, type), 1195240Sigor@sysoev.ru }, 1196240Sigor@sysoev.ru 1197240Sigor@sysoev.ru { 1198240Sigor@sysoev.ru nxt_string("version"), 1199354Svbart@nginx.com NXT_CONF_MAP_CSTRZ, 1200240Sigor@sysoev.ru offsetof(nxt_app_lang_module_t, version), 1201240Sigor@sysoev.ru }, 1202240Sigor@sysoev.ru 1203240Sigor@sysoev.ru { 1204240Sigor@sysoev.ru nxt_string("file"), 1205240Sigor@sysoev.ru NXT_CONF_MAP_CSTRZ, 1206240Sigor@sysoev.ru offsetof(nxt_app_lang_module_t, file), 1207240Sigor@sysoev.ru }, 1208240Sigor@sysoev.ru }; 1209240Sigor@sysoev.ru 1210240Sigor@sysoev.ru 12111489St.nateldemoura@f5.com static nxt_conf_map_t nxt_app_lang_mounts_map[] = { 12121489St.nateldemoura@f5.com { 12131489St.nateldemoura@f5.com nxt_string("src"), 12141489St.nateldemoura@f5.com NXT_CONF_MAP_CSTRZ, 12151489St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, src), 12161489St.nateldemoura@f5.com }, 12171489St.nateldemoura@f5.com { 12181489St.nateldemoura@f5.com nxt_string("dst"), 12191489St.nateldemoura@f5.com NXT_CONF_MAP_CSTRZ, 12201489St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, dst), 12211489St.nateldemoura@f5.com }, 12221489St.nateldemoura@f5.com { 12231673St.nateldemoura@f5.com nxt_string("name"), 12241489St.nateldemoura@f5.com NXT_CONF_MAP_CSTRZ, 12251673St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, name), 12261673St.nateldemoura@f5.com }, 12271673St.nateldemoura@f5.com { 12281673St.nateldemoura@f5.com nxt_string("type"), 12291673St.nateldemoura@f5.com NXT_CONF_MAP_INT, 12301673St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, type), 12311489St.nateldemoura@f5.com }, 12321489St.nateldemoura@f5.com { 12331489St.nateldemoura@f5.com nxt_string("flags"), 12341489St.nateldemoura@f5.com NXT_CONF_MAP_INT, 12351489St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, flags), 12361489St.nateldemoura@f5.com }, 12371489St.nateldemoura@f5.com { 12381489St.nateldemoura@f5.com nxt_string("data"), 12391489St.nateldemoura@f5.com NXT_CONF_MAP_CSTRZ, 12401489St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, data), 12411489St.nateldemoura@f5.com }, 12421489St.nateldemoura@f5.com }; 12431489St.nateldemoura@f5.com 12441489St.nateldemoura@f5.com 1245240Sigor@sysoev.ru static void 1246240Sigor@sysoev.ru nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1247240Sigor@sysoev.ru { 12481489St.nateldemoura@f5.com uint32_t index, jindex, nmounts; 1249240Sigor@sysoev.ru nxt_mp_t *mp; 1250240Sigor@sysoev.ru nxt_int_t ret; 1251240Sigor@sysoev.ru nxt_buf_t *b; 1252549Svbart@nginx.com nxt_port_t *port; 1253240Sigor@sysoev.ru nxt_runtime_t *rt; 12541489St.nateldemoura@f5.com nxt_fs_mount_t *mnt; 12551489St.nateldemoura@f5.com nxt_conf_value_t *conf, *root, *value, *mounts; 1256240Sigor@sysoev.ru nxt_app_lang_module_t *lang; 1257240Sigor@sysoev.ru 12581182St.nateldemoura@f5.com static nxt_str_t root_path = nxt_string("/"); 12591489St.nateldemoura@f5.com static nxt_str_t mounts_name = nxt_string("mounts"); 1260240Sigor@sysoev.ru 1261240Sigor@sysoev.ru rt = task->thread->runtime; 1262240Sigor@sysoev.ru 1263240Sigor@sysoev.ru if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) { 1264240Sigor@sysoev.ru return; 1265240Sigor@sysoev.ru } 1266240Sigor@sysoev.ru 12671211Smax.romanov@nginx.com if (nxt_exiting) { 12681211Smax.romanov@nginx.com nxt_debug(task, "ignoring discovered modules, exiting"); 12691211Smax.romanov@nginx.com return; 12701211Smax.romanov@nginx.com } 12711211Smax.romanov@nginx.com 1272549Svbart@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 1273549Svbart@nginx.com msg->port_msg.reply_port); 1274549Svbart@nginx.com 1275549Svbart@nginx.com if (nxt_fast_path(port != NULL)) { 1276549Svbart@nginx.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, 1277549Svbart@nginx.com msg->port_msg.stream, 0, NULL); 1278549Svbart@nginx.com } 1279549Svbart@nginx.com 1280240Sigor@sysoev.ru b = msg->buf; 1281240Sigor@sysoev.ru 1282240Sigor@sysoev.ru if (b == NULL) { 1283240Sigor@sysoev.ru return; 1284240Sigor@sysoev.ru } 1285240Sigor@sysoev.ru 1286240Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 1287240Sigor@sysoev.ru if (mp == NULL) { 1288240Sigor@sysoev.ru return; 1289240Sigor@sysoev.ru } 1290240Sigor@sysoev.ru 1291352Smax.romanov@nginx.com b = nxt_buf_chk_make_plain(mp, b, msg->size); 1292352Smax.romanov@nginx.com 1293352Smax.romanov@nginx.com if (b == NULL) { 1294352Smax.romanov@nginx.com return; 1295352Smax.romanov@nginx.com } 1296352Smax.romanov@nginx.com 1297352Smax.romanov@nginx.com nxt_debug(task, "application languages: \"%*s\"", 1298352Smax.romanov@nginx.com b->mem.free - b->mem.pos, b->mem.pos); 1299352Smax.romanov@nginx.com 1300240Sigor@sysoev.ru conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL); 1301240Sigor@sysoev.ru if (conf == NULL) { 1302240Sigor@sysoev.ru goto fail; 1303240Sigor@sysoev.ru } 1304240Sigor@sysoev.ru 1305240Sigor@sysoev.ru root = nxt_conf_get_path(conf, &root_path); 1306240Sigor@sysoev.ru if (root == NULL) { 1307240Sigor@sysoev.ru goto fail; 1308240Sigor@sysoev.ru } 1309240Sigor@sysoev.ru 1310240Sigor@sysoev.ru for (index = 0; /* void */ ; index++) { 1311240Sigor@sysoev.ru value = nxt_conf_get_array_element(root, index); 1312240Sigor@sysoev.ru if (value == NULL) { 1313240Sigor@sysoev.ru break; 1314240Sigor@sysoev.ru } 1315240Sigor@sysoev.ru 13161489St.nateldemoura@f5.com lang = nxt_array_zero_add(rt->languages); 1317240Sigor@sysoev.ru if (lang == NULL) { 1318240Sigor@sysoev.ru goto fail; 1319240Sigor@sysoev.ru } 1320240Sigor@sysoev.ru 1321240Sigor@sysoev.ru lang->module = NULL; 1322240Sigor@sysoev.ru 1323240Sigor@sysoev.ru ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map, 1324240Sigor@sysoev.ru nxt_nitems(nxt_app_lang_module_map), lang); 1325240Sigor@sysoev.ru 1326240Sigor@sysoev.ru if (ret != NXT_OK) { 1327240Sigor@sysoev.ru goto fail; 1328240Sigor@sysoev.ru } 1329240Sigor@sysoev.ru 13301489St.nateldemoura@f5.com mounts = nxt_conf_get_object_member(value, &mounts_name, NULL); 13311489St.nateldemoura@f5.com if (mounts == NULL) { 13321489St.nateldemoura@f5.com nxt_alert(task, "missing mounts from discovery message."); 13331489St.nateldemoura@f5.com goto fail; 13341489St.nateldemoura@f5.com } 13351489St.nateldemoura@f5.com 13361489St.nateldemoura@f5.com if (nxt_conf_type(mounts) != NXT_CONF_ARRAY) { 13371489St.nateldemoura@f5.com nxt_alert(task, "invalid mounts type from discovery message."); 13381489St.nateldemoura@f5.com goto fail; 13391489St.nateldemoura@f5.com } 13401489St.nateldemoura@f5.com 13411489St.nateldemoura@f5.com nmounts = nxt_conf_array_elements_count(mounts); 13421489St.nateldemoura@f5.com 13431489St.nateldemoura@f5.com lang->mounts = nxt_array_create(rt->mem_pool, nmounts, 13441489St.nateldemoura@f5.com sizeof(nxt_fs_mount_t)); 13451489St.nateldemoura@f5.com 13461489St.nateldemoura@f5.com if (lang->mounts == NULL) { 13471489St.nateldemoura@f5.com goto fail; 13481489St.nateldemoura@f5.com } 13491489St.nateldemoura@f5.com 13501489St.nateldemoura@f5.com for (jindex = 0; /* */; jindex++) { 13511489St.nateldemoura@f5.com value = nxt_conf_get_array_element(mounts, jindex); 13521489St.nateldemoura@f5.com if (value == NULL) { 13531489St.nateldemoura@f5.com break; 13541489St.nateldemoura@f5.com } 13551489St.nateldemoura@f5.com 13561489St.nateldemoura@f5.com mnt = nxt_array_zero_add(lang->mounts); 13571489St.nateldemoura@f5.com if (mnt == NULL) { 13581489St.nateldemoura@f5.com goto fail; 13591489St.nateldemoura@f5.com } 13601489St.nateldemoura@f5.com 13611585St.nateldemoura@f5.com mnt->builtin = 1; 13621673St.nateldemoura@f5.com mnt->deps = 1; 13631585St.nateldemoura@f5.com 13641489St.nateldemoura@f5.com ret = nxt_conf_map_object(rt->mem_pool, value, 13651489St.nateldemoura@f5.com nxt_app_lang_mounts_map, 13661489St.nateldemoura@f5.com nxt_nitems(nxt_app_lang_mounts_map), mnt); 13671489St.nateldemoura@f5.com 13681489St.nateldemoura@f5.com if (ret != NXT_OK) { 13691489St.nateldemoura@f5.com goto fail; 13701489St.nateldemoura@f5.com } 13711489St.nateldemoura@f5.com } 13721489St.nateldemoura@f5.com 13731489St.nateldemoura@f5.com nxt_debug(task, "lang %d %s \"%s\" (%d mounts)", 13741489St.nateldemoura@f5.com lang->type, lang->version, lang->file, lang->mounts->nelts); 1375240Sigor@sysoev.ru } 1376240Sigor@sysoev.ru 1377240Sigor@sysoev.ru qsort(rt->languages->elts, rt->languages->nelts, 1378240Sigor@sysoev.ru sizeof(nxt_app_lang_module_t), nxt_app_lang_compare); 1379240Sigor@sysoev.ru 1380240Sigor@sysoev.ru fail: 1381240Sigor@sysoev.ru 1382240Sigor@sysoev.ru nxt_mp_destroy(mp); 1383240Sigor@sysoev.ru 13841488St.nateldemoura@f5.com ret = nxt_main_process_create(task, nxt_controller_process); 13851488St.nateldemoura@f5.com if (ret == NXT_OK) { 13861488St.nateldemoura@f5.com ret = nxt_main_process_create(task, nxt_router_process); 13871488St.nateldemoura@f5.com } 1388240Sigor@sysoev.ru 13891488St.nateldemoura@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 13901488St.nateldemoura@f5.com nxt_exiting = 1; 13911488St.nateldemoura@f5.com 13921488St.nateldemoura@f5.com nxt_runtime_quit(task, 1); 1393240Sigor@sysoev.ru } 1394240Sigor@sysoev.ru } 1395240Sigor@sysoev.ru 1396240Sigor@sysoev.ru 1397240Sigor@sysoev.ru static int nxt_cdecl 1398240Sigor@sysoev.ru nxt_app_lang_compare(const void *v1, const void *v2) 1399240Sigor@sysoev.ru { 1400240Sigor@sysoev.ru int n; 1401240Sigor@sysoev.ru const nxt_app_lang_module_t *lang1, *lang2; 1402240Sigor@sysoev.ru 1403240Sigor@sysoev.ru lang1 = v1; 1404240Sigor@sysoev.ru lang2 = v2; 1405240Sigor@sysoev.ru 1406356Svbart@nginx.com n = lang1->type - lang2->type; 1407258Sigor@sysoev.ru 1408258Sigor@sysoev.ru if (n != 0) { 1409258Sigor@sysoev.ru return n; 1410258Sigor@sysoev.ru } 1411258Sigor@sysoev.ru 1412354Svbart@nginx.com n = nxt_strverscmp(lang1->version, lang2->version); 1413240Sigor@sysoev.ru 1414240Sigor@sysoev.ru /* Negate result to move higher versions to the beginning. */ 1415240Sigor@sysoev.ru 1416240Sigor@sysoev.ru return -n; 1417240Sigor@sysoev.ru } 1418314Svbart@nginx.com 1419314Svbart@nginx.com 1420314Svbart@nginx.com static void 1421314Svbart@nginx.com nxt_main_port_conf_store_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1422314Svbart@nginx.com { 14231787Smax.romanov@nginx.com void *p; 14241787Smax.romanov@nginx.com size_t size; 14251787Smax.romanov@nginx.com ssize_t n; 1426314Svbart@nginx.com nxt_int_t ret; 1427314Svbart@nginx.com nxt_file_t file; 1428314Svbart@nginx.com nxt_runtime_t *rt; 1429314Svbart@nginx.com 14301787Smax.romanov@nginx.com p = MAP_FAILED; 14311787Smax.romanov@nginx.com 14321787Smax.romanov@nginx.com /* 14331787Smax.romanov@nginx.com * Ancient compilers like gcc 4.8.5 on CentOS 7 wants 'size' to be 14341787Smax.romanov@nginx.com * initialized in 'cleanup' section. 14351787Smax.romanov@nginx.com */ 14361787Smax.romanov@nginx.com size = 0; 14371787Smax.romanov@nginx.com 14381787Smax.romanov@nginx.com if (nxt_slow_path(msg->fd[0] == -1)) { 14391787Smax.romanov@nginx.com nxt_alert(task, "conf_store_handler: invalid shm fd"); 14401787Smax.romanov@nginx.com goto error; 14411787Smax.romanov@nginx.com } 14421787Smax.romanov@nginx.com 14431787Smax.romanov@nginx.com if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) { 14441787Smax.romanov@nginx.com nxt_alert(task, "conf_store_handler: unexpected buffer size (%d)", 14451787Smax.romanov@nginx.com (int) nxt_buf_mem_used_size(&msg->buf->mem)); 14461787Smax.romanov@nginx.com goto error; 14471787Smax.romanov@nginx.com } 14481787Smax.romanov@nginx.com 14491787Smax.romanov@nginx.com nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t)); 14501787Smax.romanov@nginx.com 14511787Smax.romanov@nginx.com p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd[0], 0); 14521787Smax.romanov@nginx.com 14531787Smax.romanov@nginx.com nxt_fd_close(msg->fd[0]); 14541787Smax.romanov@nginx.com msg->fd[0] = -1; 14551787Smax.romanov@nginx.com 14561787Smax.romanov@nginx.com if (nxt_slow_path(p == MAP_FAILED)) { 14571787Smax.romanov@nginx.com goto error; 14581787Smax.romanov@nginx.com } 14591787Smax.romanov@nginx.com 14601787Smax.romanov@nginx.com nxt_debug(task, "conf_store_handler(%uz): %*s", size, size, p); 14611787Smax.romanov@nginx.com 1462314Svbart@nginx.com nxt_memzero(&file, sizeof(nxt_file_t)); 1463314Svbart@nginx.com 1464314Svbart@nginx.com rt = task->thread->runtime; 1465314Svbart@nginx.com 1466314Svbart@nginx.com file.name = (nxt_file_name_t *) rt->conf_tmp; 1467314Svbart@nginx.com 1468314Svbart@nginx.com if (nxt_slow_path(nxt_file_open(task, &file, NXT_FILE_WRONLY, 1469314Svbart@nginx.com NXT_FILE_TRUNCATE, NXT_FILE_OWNER_ACCESS) 1470314Svbart@nginx.com != NXT_OK)) 1471314Svbart@nginx.com { 1472314Svbart@nginx.com goto error; 1473314Svbart@nginx.com } 1474314Svbart@nginx.com 14751787Smax.romanov@nginx.com n = nxt_file_write(&file, p, size, 0); 1476314Svbart@nginx.com 1477314Svbart@nginx.com nxt_file_close(task, &file); 1478314Svbart@nginx.com 14791787Smax.romanov@nginx.com if (nxt_slow_path(n != (ssize_t) size)) { 14801787Smax.romanov@nginx.com (void) nxt_file_delete(file.name); 14811787Smax.romanov@nginx.com goto error; 14821787Smax.romanov@nginx.com } 14831787Smax.romanov@nginx.com 1484314Svbart@nginx.com ret = nxt_file_rename(file.name, (nxt_file_name_t *) rt->conf); 1485314Svbart@nginx.com 1486314Svbart@nginx.com if (nxt_fast_path(ret == NXT_OK)) { 14871787Smax.romanov@nginx.com goto cleanup; 1488314Svbart@nginx.com } 1489314Svbart@nginx.com 1490314Svbart@nginx.com error: 1491314Svbart@nginx.com 1492564Svbart@nginx.com nxt_alert(task, "failed to store current configuration"); 14931787Smax.romanov@nginx.com 14941787Smax.romanov@nginx.com cleanup: 14951787Smax.romanov@nginx.com 14961787Smax.romanov@nginx.com if (p != MAP_FAILED) { 14971787Smax.romanov@nginx.com nxt_mem_munmap(p, size); 14981787Smax.romanov@nginx.com } 14991787Smax.romanov@nginx.com 15001787Smax.romanov@nginx.com if (msg->fd[0] != -1) { 15011787Smax.romanov@nginx.com nxt_fd_close(msg->fd[0]); 15021787Smax.romanov@nginx.com msg->fd[0] = -1; 15031787Smax.romanov@nginx.com } 1504314Svbart@nginx.com } 1505630Svbart@nginx.com 1506630Svbart@nginx.com 1507630Svbart@nginx.com static void 1508630Svbart@nginx.com nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1509630Svbart@nginx.com { 1510630Svbart@nginx.com u_char *path; 1511630Svbart@nginx.com nxt_int_t ret; 1512630Svbart@nginx.com nxt_file_t file; 1513630Svbart@nginx.com nxt_port_t *port; 1514630Svbart@nginx.com nxt_port_msg_type_t type; 1515630Svbart@nginx.com 1516630Svbart@nginx.com nxt_debug(task, "opening access log file"); 1517630Svbart@nginx.com 1518630Svbart@nginx.com path = msg->buf->mem.pos; 1519630Svbart@nginx.com 1520630Svbart@nginx.com nxt_memzero(&file, sizeof(nxt_file_t)); 1521630Svbart@nginx.com 1522630Svbart@nginx.com file.name = (nxt_file_name_t *) path; 1523630Svbart@nginx.com file.log_level = NXT_LOG_ERR; 1524630Svbart@nginx.com 1525630Svbart@nginx.com ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, 1526630Svbart@nginx.com NXT_FILE_OWNER_ACCESS); 1527630Svbart@nginx.com 1528630Svbart@nginx.com type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD 1529630Svbart@nginx.com : NXT_PORT_MSG_RPC_ERROR; 1530630Svbart@nginx.com 1531630Svbart@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 1532630Svbart@nginx.com msg->port_msg.reply_port); 1533630Svbart@nginx.com 1534630Svbart@nginx.com if (nxt_fast_path(port != NULL)) { 1535630Svbart@nginx.com (void) nxt_port_socket_write(task, port, type, file.fd, 1536630Svbart@nginx.com msg->port_msg.stream, 0, NULL); 1537630Svbart@nginx.com } 1538630Svbart@nginx.com } 1539