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"), 185240Sigor@sysoev.ru NXT_CONF_MAP_STR, 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 }, 200*1681Smax.romanov@nginx.com 201*1681Smax.romanov@nginx.com { 202*1681Smax.romanov@nginx.com nxt_string("threads"), 203*1681Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 204*1681Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.python.threads), 205*1681Smax.romanov@nginx.com }, 206*1681Smax.romanov@nginx.com 207*1681Smax.romanov@nginx.com { 208*1681Smax.romanov@nginx.com nxt_string("thread_stack_size"), 209*1681Smax.romanov@nginx.com NXT_CONF_MAP_INT32, 210*1681Smax.romanov@nginx.com offsetof(nxt_common_app_conf_t, u.python.thread_stack_size), 211*1681Smax.romanov@nginx.com }, 212510Salexander.borisov@nginx.com }; 213240Sigor@sysoev.ru 214510Salexander.borisov@nginx.com 215546Smax.romanov@nginx.com static nxt_conf_map_t nxt_php_app_conf[] = { 216240Sigor@sysoev.ru { 2171473Svbart@nginx.com nxt_string("targets"), 2181473Svbart@nginx.com NXT_CONF_MAP_PTR, 2191473Svbart@nginx.com offsetof(nxt_common_app_conf_t, u.php.targets), 220240Sigor@sysoev.ru }, 221687Svbart@nginx.com 222687Svbart@nginx.com { 223687Svbart@nginx.com nxt_string("options"), 224687Svbart@nginx.com NXT_CONF_MAP_PTR, 225687Svbart@nginx.com offsetof(nxt_common_app_conf_t, u.php.options), 226687Svbart@nginx.com }, 227510Salexander.borisov@nginx.com }; 228240Sigor@sysoev.ru 229510Salexander.borisov@nginx.com 230546Smax.romanov@nginx.com static nxt_conf_map_t nxt_perl_app_conf[] = { 231510Salexander.borisov@nginx.com { 232510Salexander.borisov@nginx.com nxt_string("script"), 233510Salexander.borisov@nginx.com NXT_CONF_MAP_CSTRZ, 234510Salexander.borisov@nginx.com offsetof(nxt_common_app_conf_t, u.perl.script), 235510Salexander.borisov@nginx.com }, 236510Salexander.borisov@nginx.com }; 237510Salexander.borisov@nginx.com 238510Salexander.borisov@nginx.com 239584Salexander.borisov@nginx.com static nxt_conf_map_t nxt_ruby_app_conf[] = { 240584Salexander.borisov@nginx.com { 241584Salexander.borisov@nginx.com nxt_string("script"), 242584Salexander.borisov@nginx.com NXT_CONF_MAP_STR, 243584Salexander.borisov@nginx.com offsetof(nxt_common_app_conf_t, u.ruby.script), 244584Salexander.borisov@nginx.com }, 245584Salexander.borisov@nginx.com }; 246584Salexander.borisov@nginx.com 247584Salexander.borisov@nginx.com 248977Smax.romanov@gmail.com static nxt_conf_map_t nxt_java_app_conf[] = { 249977Smax.romanov@gmail.com { 250977Smax.romanov@gmail.com nxt_string("classpath"), 251977Smax.romanov@gmail.com NXT_CONF_MAP_PTR, 252977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.classpath), 253977Smax.romanov@gmail.com }, 254977Smax.romanov@gmail.com { 255977Smax.romanov@gmail.com nxt_string("webapp"), 256977Smax.romanov@gmail.com NXT_CONF_MAP_CSTRZ, 257977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.webapp), 258977Smax.romanov@gmail.com }, 259977Smax.romanov@gmail.com { 260977Smax.romanov@gmail.com nxt_string("options"), 261977Smax.romanov@gmail.com NXT_CONF_MAP_PTR, 262977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.options), 263977Smax.romanov@gmail.com }, 264977Smax.romanov@gmail.com { 265977Smax.romanov@gmail.com nxt_string("unit_jars"), 266977Smax.romanov@gmail.com NXT_CONF_MAP_CSTRZ, 267977Smax.romanov@gmail.com offsetof(nxt_common_app_conf_t, u.java.unit_jars), 268977Smax.romanov@gmail.com }, 269977Smax.romanov@gmail.com 270977Smax.romanov@gmail.com }; 271977Smax.romanov@gmail.com 272977Smax.romanov@gmail.com 273546Smax.romanov@nginx.com static nxt_conf_app_map_t nxt_app_maps[] = { 274804Svbart@nginx.com { nxt_nitems(nxt_external_app_conf), nxt_external_app_conf }, 275804Svbart@nginx.com { nxt_nitems(nxt_python_app_conf), nxt_python_app_conf }, 276804Svbart@nginx.com { nxt_nitems(nxt_php_app_conf), nxt_php_app_conf }, 277804Svbart@nginx.com { nxt_nitems(nxt_perl_app_conf), nxt_perl_app_conf }, 278804Svbart@nginx.com { nxt_nitems(nxt_ruby_app_conf), nxt_ruby_app_conf }, 279977Smax.romanov@gmail.com { nxt_nitems(nxt_java_app_conf), nxt_java_app_conf }, 280510Salexander.borisov@nginx.com }; 281510Salexander.borisov@nginx.com 282510Salexander.borisov@nginx.com 283240Sigor@sysoev.ru static void 284240Sigor@sysoev.ru nxt_port_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 285240Sigor@sysoev.ru { 286240Sigor@sysoev.ru nxt_debug(task, "main data: %*s", 287240Sigor@sysoev.ru nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos); 288240Sigor@sysoev.ru } 289240Sigor@sysoev.ru 290240Sigor@sysoev.ru 291240Sigor@sysoev.ru static void 2921488St.nateldemoura@f5.com nxt_port_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 293240Sigor@sysoev.ru { 2941488St.nateldemoura@f5.com u_char *start, *p, ch; 295536Svbart@nginx.com size_t type_len; 296536Svbart@nginx.com nxt_int_t ret; 297240Sigor@sysoev.ru nxt_buf_t *b; 298318Smax.romanov@nginx.com nxt_port_t *port; 2991182St.nateldemoura@f5.com nxt_runtime_t *rt; 3001488St.nateldemoura@f5.com nxt_process_t *process; 301536Svbart@nginx.com nxt_app_type_t idx; 302240Sigor@sysoev.ru nxt_conf_value_t *conf; 3031488St.nateldemoura@f5.com nxt_process_init_t *init; 3041488St.nateldemoura@f5.com nxt_common_app_conf_t *app_conf; 305240Sigor@sysoev.ru 306318Smax.romanov@nginx.com ret = NXT_ERROR; 307318Smax.romanov@nginx.com 3081488St.nateldemoura@f5.com rt = task->thread->runtime; 309352Smax.romanov@nginx.com 3101488St.nateldemoura@f5.com process = nxt_main_process_new(task, rt); 3111488St.nateldemoura@f5.com if (nxt_slow_path(process == NULL)) { 312352Smax.romanov@nginx.com return; 313352Smax.romanov@nginx.com } 314352Smax.romanov@nginx.com 3151488St.nateldemoura@f5.com init = nxt_process_init(process); 3161488St.nateldemoura@f5.com 3171488St.nateldemoura@f5.com *init = nxt_app_process; 318352Smax.romanov@nginx.com 3191488St.nateldemoura@f5.com b = nxt_buf_chk_make_plain(process->mem_pool, msg->buf, msg->size); 320352Smax.romanov@nginx.com if (b == NULL) { 3211488St.nateldemoura@f5.com goto failed; 322352Smax.romanov@nginx.com } 323240Sigor@sysoev.ru 3241488St.nateldemoura@f5.com nxt_debug(task, "main start process: %*s", b->mem.free - b->mem.pos, 325240Sigor@sysoev.ru b->mem.pos); 326240Sigor@sysoev.ru 3271488St.nateldemoura@f5.com app_conf = nxt_mp_zalloc(process->mem_pool, sizeof(nxt_common_app_conf_t)); 3281488St.nateldemoura@f5.com if (nxt_slow_path(app_conf == NULL)) { 3291488St.nateldemoura@f5.com goto failed; 3301488St.nateldemoura@f5.com } 331240Sigor@sysoev.ru 332240Sigor@sysoev.ru start = b->mem.pos; 333240Sigor@sysoev.ru 3341488St.nateldemoura@f5.com app_conf->name.start = start; 3351488St.nateldemoura@f5.com app_conf->name.length = nxt_strlen(start); 3361488St.nateldemoura@f5.com 3371488St.nateldemoura@f5.com init->name = (const char *) start; 3381488St.nateldemoura@f5.com 3391488St.nateldemoura@f5.com process->name = nxt_mp_alloc(process->mem_pool, app_conf->name.length 3401488St.nateldemoura@f5.com + sizeof("\"\" application") + 1); 3411488St.nateldemoura@f5.com 3421488St.nateldemoura@f5.com if (nxt_slow_path(process->name == NULL)) { 3431488St.nateldemoura@f5.com goto failed; 3441488St.nateldemoura@f5.com } 345240Sigor@sysoev.ru 3461488St.nateldemoura@f5.com p = (u_char *) process->name; 3471488St.nateldemoura@f5.com *p++ = '"'; 3481488St.nateldemoura@f5.com p = nxt_cpymem(p, init->name, app_conf->name.length); 3491488St.nateldemoura@f5.com p = nxt_cpymem(p, "\" application", 13); 3501488St.nateldemoura@f5.com *p = '\0'; 351240Sigor@sysoev.ru 3521488St.nateldemoura@f5.com app_conf->shm_limit = 100 * 1024 * 1024; 353240Sigor@sysoev.ru 3541488St.nateldemoura@f5.com start += app_conf->name.length + 1; 3551488St.nateldemoura@f5.com 3561488St.nateldemoura@f5.com conf = nxt_conf_json_parse(process->mem_pool, start, b->mem.free, NULL); 357240Sigor@sysoev.ru if (conf == NULL) { 358564Svbart@nginx.com nxt_alert(task, "router app configuration parsing error"); 359318Smax.romanov@nginx.com 360318Smax.romanov@nginx.com goto failed; 361240Sigor@sysoev.ru } 362240Sigor@sysoev.ru 3631182St.nateldemoura@f5.com rt = task->thread->runtime; 3641182St.nateldemoura@f5.com 3651488St.nateldemoura@f5.com app_conf->user.start = (u_char*)rt->user_cred.user; 3661488St.nateldemoura@f5.com app_conf->user.length = nxt_strlen(rt->user_cred.user); 367240Sigor@sysoev.ru 3681488St.nateldemoura@f5.com ret = nxt_conf_map_object(process->mem_pool, conf, nxt_common_app_conf, 3691488St.nateldemoura@f5.com nxt_nitems(nxt_common_app_conf), app_conf); 3701488St.nateldemoura@f5.com 371240Sigor@sysoev.ru if (ret != NXT_OK) { 372564Svbart@nginx.com nxt_alert(task, "failed to map common app conf received from router"); 373318Smax.romanov@nginx.com goto failed; 374240Sigor@sysoev.ru } 375240Sigor@sysoev.ru 3761488St.nateldemoura@f5.com for (type_len = 0; type_len != app_conf->type.length; type_len++) { 3771488St.nateldemoura@f5.com ch = app_conf->type.start[type_len]; 378536Svbart@nginx.com 379536Svbart@nginx.com if (ch == ' ' || nxt_isdigit(ch)) { 380536Svbart@nginx.com break; 381536Svbart@nginx.com } 382536Svbart@nginx.com } 383536Svbart@nginx.com 3841488St.nateldemoura@f5.com idx = nxt_app_parse_type(app_conf->type.start, type_len); 385510Salexander.borisov@nginx.com 386546Smax.romanov@nginx.com if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) { 387564Svbart@nginx.com nxt_alert(task, "invalid app type %d received from router", (int) idx); 388546Smax.romanov@nginx.com goto failed; 389546Smax.romanov@nginx.com } 390510Salexander.borisov@nginx.com 3911488St.nateldemoura@f5.com ret = nxt_conf_map_object(process->mem_pool, conf, nxt_app_maps[idx].map, 3921488St.nateldemoura@f5.com nxt_app_maps[idx].size, app_conf); 393510Salexander.borisov@nginx.com 394546Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 395564Svbart@nginx.com nxt_alert(task, "failed to map app conf received from router"); 396546Smax.romanov@nginx.com goto failed; 397546Smax.romanov@nginx.com } 398510Salexander.borisov@nginx.com 3991488St.nateldemoura@f5.com if (app_conf->limits != NULL) { 4001488St.nateldemoura@f5.com ret = nxt_conf_map_object(process->mem_pool, app_conf->limits, 4011320Smax.romanov@nginx.com nxt_common_app_limits_conf, 4021320Smax.romanov@nginx.com nxt_nitems(nxt_common_app_limits_conf), 4031488St.nateldemoura@f5.com app_conf); 4041320Smax.romanov@nginx.com 4051320Smax.romanov@nginx.com if (nxt_slow_path(ret != NXT_OK)) { 4061320Smax.romanov@nginx.com nxt_alert(task, "failed to map app limits received from router"); 4071320Smax.romanov@nginx.com goto failed; 4081320Smax.romanov@nginx.com } 4091320Smax.romanov@nginx.com } 4101320Smax.romanov@nginx.com 4111488St.nateldemoura@f5.com app_conf->self = conf; 4121488St.nateldemoura@f5.com 4131488St.nateldemoura@f5.com process->stream = msg->port_msg.stream; 4141488St.nateldemoura@f5.com process->data.app = app_conf; 4151473Svbart@nginx.com 4161488St.nateldemoura@f5.com ret = nxt_main_start_process(task, process); 4171488St.nateldemoura@f5.com if (nxt_fast_path(ret == NXT_OK || ret == NXT_AGAIN)) { 4181488St.nateldemoura@f5.com return; 4191488St.nateldemoura@f5.com } 420240Sigor@sysoev.ru 421318Smax.romanov@nginx.com failed: 422318Smax.romanov@nginx.com 4231488St.nateldemoura@f5.com nxt_process_use(task, process, -1); 4241488St.nateldemoura@f5.com 4251488St.nateldemoura@f5.com port = nxt_runtime_port_find(rt, msg->port_msg.pid, 4261488St.nateldemoura@f5.com msg->port_msg.reply_port); 4271488St.nateldemoura@f5.com 4281488St.nateldemoura@f5.com if (nxt_fast_path(port != NULL)) { 4291488St.nateldemoura@f5.com nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, 4301488St.nateldemoura@f5.com -1, msg->port_msg.stream, 0, NULL); 4311488St.nateldemoura@f5.com } 4321488St.nateldemoura@f5.com } 4331488St.nateldemoura@f5.com 4341488St.nateldemoura@f5.com 4351488St.nateldemoura@f5.com static void 4361488St.nateldemoura@f5.com nxt_main_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 4371488St.nateldemoura@f5.com { 4381488St.nateldemoura@f5.com nxt_port_t *port; 4391488St.nateldemoura@f5.com nxt_process_t *process; 4401488St.nateldemoura@f5.com nxt_runtime_t *rt; 4411488St.nateldemoura@f5.com 4421488St.nateldemoura@f5.com rt = task->thread->runtime; 4431488St.nateldemoura@f5.com 4441488St.nateldemoura@f5.com process = nxt_runtime_process_find(rt, msg->port_msg.pid); 4451488St.nateldemoura@f5.com if (nxt_slow_path(process == NULL)) { 4461488St.nateldemoura@f5.com return; 447318Smax.romanov@nginx.com } 448318Smax.romanov@nginx.com 4491488St.nateldemoura@f5.com nxt_assert(process->state == NXT_PROCESS_STATE_CREATING); 4501488St.nateldemoura@f5.com 4511488St.nateldemoura@f5.com port = nxt_runtime_port_find(rt, msg->port_msg.pid, 4521488St.nateldemoura@f5.com msg->port_msg.reply_port); 4531488St.nateldemoura@f5.com 4541488St.nateldemoura@f5.com 4551488St.nateldemoura@f5.com if (nxt_slow_path(port == NULL)) { 4561488St.nateldemoura@f5.com return; 4571488St.nateldemoura@f5.com } 4581488St.nateldemoura@f5.com 4591488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER) 4601488St.nateldemoura@f5.com if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) { 4611488St.nateldemoura@f5.com if (nxt_slow_path(nxt_clone_credential_map(task, process->pid, 4621488St.nateldemoura@f5.com process->user_cred, 4631488St.nateldemoura@f5.com &process->isolation.clone) 4641488St.nateldemoura@f5.com != NXT_OK)) 4651488St.nateldemoura@f5.com { 4661488St.nateldemoura@f5.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, 4671488St.nateldemoura@f5.com -1, msg->port_msg.stream, 0, NULL); 4681488St.nateldemoura@f5.com return; 4691488St.nateldemoura@f5.com } 4701488St.nateldemoura@f5.com } 4711488St.nateldemoura@f5.com 4721488St.nateldemoura@f5.com #endif 4731488St.nateldemoura@f5.com 4741488St.nateldemoura@f5.com process->state = NXT_PROCESS_STATE_CREATED; 4751488St.nateldemoura@f5.com 4761488St.nateldemoura@f5.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST, 4771488St.nateldemoura@f5.com -1, msg->port_msg.stream, 0, NULL); 478240Sigor@sysoev.ru } 479240Sigor@sysoev.ru 480240Sigor@sysoev.ru 481320Smax.romanov@nginx.com static nxt_port_handlers_t nxt_main_process_port_handlers = { 4821488St.nateldemoura@f5.com .data = nxt_port_main_data_handler, 4831488St.nateldemoura@f5.com .process_created = nxt_main_process_created_handler, 4841488St.nateldemoura@f5.com .process_ready = nxt_port_process_ready_handler, 4851488St.nateldemoura@f5.com .start_process = nxt_port_main_start_process_handler, 4861488St.nateldemoura@f5.com .socket = nxt_main_port_socket_handler, 4871488St.nateldemoura@f5.com .modules = nxt_main_port_modules_handler, 4881488St.nateldemoura@f5.com .conf_store = nxt_main_port_conf_store_handler, 489774Svbart@nginx.com #if (NXT_TLS) 4901488St.nateldemoura@f5.com .cert_get = nxt_cert_store_get_handler, 4911488St.nateldemoura@f5.com .cert_delete = nxt_cert_store_delete_handler, 492774Svbart@nginx.com #endif 4931488St.nateldemoura@f5.com .access_log = nxt_main_port_access_log_handler, 4941488St.nateldemoura@f5.com .rpc_ready = nxt_port_rpc_handler, 4951488St.nateldemoura@f5.com .rpc_error = nxt_port_rpc_handler, 496240Sigor@sysoev.ru }; 497240Sigor@sysoev.ru 498240Sigor@sysoev.ru 499240Sigor@sysoev.ru static nxt_int_t 500240Sigor@sysoev.ru nxt_main_process_port_create(nxt_task_t *task, nxt_runtime_t *rt) 501240Sigor@sysoev.ru { 502240Sigor@sysoev.ru nxt_int_t ret; 503240Sigor@sysoev.ru nxt_port_t *port; 504240Sigor@sysoev.ru nxt_process_t *process; 505240Sigor@sysoev.ru 5061254Shongzhidao@gmail.com port = nxt_runtime_process_port_create(task, rt, nxt_pid, 0, 5071254Shongzhidao@gmail.com NXT_PROCESS_MAIN); 508240Sigor@sysoev.ru if (nxt_slow_path(port == NULL)) { 509240Sigor@sysoev.ru return NXT_ERROR; 510240Sigor@sysoev.ru } 511240Sigor@sysoev.ru 5121254Shongzhidao@gmail.com process = port->process; 513349Smax.romanov@nginx.com 514240Sigor@sysoev.ru ret = nxt_port_socket_init(task, port, 0); 515240Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 5161488St.nateldemoura@f5.com nxt_port_use(task, port, -1); 517240Sigor@sysoev.ru return ret; 518240Sigor@sysoev.ru } 519240Sigor@sysoev.ru 520240Sigor@sysoev.ru /* 521240Sigor@sysoev.ru * A main process port. A write port is not closed 5221488St.nateldemoura@f5.com * since it should be inherited by processes. 523240Sigor@sysoev.ru */ 524320Smax.romanov@nginx.com nxt_port_enable(task, port, &nxt_main_process_port_handlers); 525240Sigor@sysoev.ru 5261488St.nateldemoura@f5.com process->state = NXT_PROCESS_STATE_READY; 527240Sigor@sysoev.ru 528240Sigor@sysoev.ru return NXT_OK; 529240Sigor@sysoev.ru } 530240Sigor@sysoev.ru 531240Sigor@sysoev.ru 532240Sigor@sysoev.ru static void 533240Sigor@sysoev.ru nxt_main_process_title(nxt_task_t *task) 534240Sigor@sysoev.ru { 535240Sigor@sysoev.ru u_char *p, *end; 536240Sigor@sysoev.ru nxt_uint_t i; 537240Sigor@sysoev.ru u_char title[2048]; 538240Sigor@sysoev.ru 539240Sigor@sysoev.ru end = title + sizeof(title) - 1; 540240Sigor@sysoev.ru 541680Sigor@sysoev.ru p = nxt_sprintf(title, end, "unit: main v" NXT_VERSION " [%s", 542680Sigor@sysoev.ru nxt_process_argv[0]); 543240Sigor@sysoev.ru 544240Sigor@sysoev.ru for (i = 1; nxt_process_argv[i] != NULL; i++) { 545240Sigor@sysoev.ru p = nxt_sprintf(p, end, " %s", nxt_process_argv[i]); 546240Sigor@sysoev.ru } 547240Sigor@sysoev.ru 548240Sigor@sysoev.ru if (p < end) { 549240Sigor@sysoev.ru *p++ = ']'; 550240Sigor@sysoev.ru } 551240Sigor@sysoev.ru 552240Sigor@sysoev.ru *p = '\0'; 553240Sigor@sysoev.ru 554240Sigor@sysoev.ru nxt_process_title(task, "%s", title); 555240Sigor@sysoev.ru } 556240Sigor@sysoev.ru 557240Sigor@sysoev.ru 558240Sigor@sysoev.ru static nxt_int_t 5591488St.nateldemoura@f5.com nxt_main_process_create(nxt_task_t *task, const nxt_process_init_t init) 560240Sigor@sysoev.ru { 5611488St.nateldemoura@f5.com nxt_int_t ret; 5621488St.nateldemoura@f5.com nxt_runtime_t *rt; 5631488St.nateldemoura@f5.com nxt_process_t *process; 5641488St.nateldemoura@f5.com nxt_process_init_t *pinit; 565240Sigor@sysoev.ru 5661488St.nateldemoura@f5.com rt = task->thread->runtime; 5671302St.nateldemoura@f5.com 5681488St.nateldemoura@f5.com process = nxt_main_process_new(task, rt); 5691488St.nateldemoura@f5.com if (nxt_slow_path(process == NULL)) { 570368Svbart@nginx.com return NXT_ERROR; 571368Svbart@nginx.com } 572368Svbart@nginx.com 5731488St.nateldemoura@f5.com process->name = init.name; 5741488St.nateldemoura@f5.com process->user_cred = &rt->user_cred; 575314Svbart@nginx.com 5761488St.nateldemoura@f5.com pinit = nxt_process_init(process); 5771488St.nateldemoura@f5.com *pinit = init; 578314Svbart@nginx.com 5791488St.nateldemoura@f5.com ret = nxt_main_start_process(task, process); 5801488St.nateldemoura@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 5811488St.nateldemoura@f5.com nxt_process_use(task, process, -1); 582314Svbart@nginx.com } 583314Svbart@nginx.com 584314Svbart@nginx.com return ret; 585240Sigor@sysoev.ru } 586240Sigor@sysoev.ru 587240Sigor@sysoev.ru 5881488St.nateldemoura@f5.com static nxt_process_t * 5891488St.nateldemoura@f5.com nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt) 590240Sigor@sysoev.ru { 5911488St.nateldemoura@f5.com nxt_process_t *process; 592240Sigor@sysoev.ru 5931488St.nateldemoura@f5.com process = nxt_runtime_process_new(rt); 5941488St.nateldemoura@f5.com if (nxt_slow_path(process == NULL)) { 5951488St.nateldemoura@f5.com return NULL; 596240Sigor@sysoev.ru } 597240Sigor@sysoev.ru 5981488St.nateldemoura@f5.com process->mem_pool = nxt_mp_create(1024, 128, 256, 32); 5991488St.nateldemoura@f5.com if (process->mem_pool == NULL) { 6001488St.nateldemoura@f5.com nxt_process_use(task, process, -1); 6011488St.nateldemoura@f5.com return NULL; 602240Sigor@sysoev.ru } 603240Sigor@sysoev.ru 6041488St.nateldemoura@f5.com return process; 605240Sigor@sysoev.ru } 606240Sigor@sysoev.ru 6071302St.nateldemoura@f5.com 608240Sigor@sysoev.ru static nxt_int_t 6091488St.nateldemoura@f5.com nxt_main_start_process(nxt_task_t *task, nxt_process_t *process) 610240Sigor@sysoev.ru { 6111488St.nateldemoura@f5.com nxt_mp_t *tmp_mp; 6121182St.nateldemoura@f5.com nxt_int_t ret; 6131488St.nateldemoura@f5.com nxt_pid_t pid; 6141488St.nateldemoura@f5.com nxt_port_t *port; 615240Sigor@sysoev.ru nxt_process_init_t *init; 616240Sigor@sysoev.ru 6171488St.nateldemoura@f5.com init = nxt_process_init(process); 618240Sigor@sysoev.ru 619240Sigor@sysoev.ru port = nxt_port_new(task, 0, 0, init->type); 620240Sigor@sysoev.ru if (nxt_slow_path(port == NULL)) { 621240Sigor@sysoev.ru return NXT_ERROR; 622240Sigor@sysoev.ru } 623240Sigor@sysoev.ru 624240Sigor@sysoev.ru nxt_process_port_add(task, process, port); 625240Sigor@sysoev.ru 626240Sigor@sysoev.ru ret = nxt_port_socket_init(task, port, 0); 627240Sigor@sysoev.ru if (nxt_slow_path(ret != NXT_OK)) { 6281565St.nateldemoura@f5.com goto free_port; 6291488St.nateldemoura@f5.com } 6301488St.nateldemoura@f5.com 6311488St.nateldemoura@f5.com tmp_mp = nxt_mp_create(1024, 128, 256, 32); 6321565St.nateldemoura@f5.com if (nxt_slow_path(tmp_mp == NULL)) { 6331565St.nateldemoura@f5.com ret = NXT_ERROR; 6341565St.nateldemoura@f5.com 6351565St.nateldemoura@f5.com goto close_port; 6361488St.nateldemoura@f5.com } 6371488St.nateldemoura@f5.com 6381488St.nateldemoura@f5.com if (init->prefork) { 6391488St.nateldemoura@f5.com ret = init->prefork(task, process, tmp_mp); 6401488St.nateldemoura@f5.com if (nxt_slow_path(ret != NXT_OK)) { 6411565St.nateldemoura@f5.com goto free_mempool; 6421488St.nateldemoura@f5.com } 643240Sigor@sysoev.ru } 644240Sigor@sysoev.ru 645240Sigor@sysoev.ru pid = nxt_process_create(task, process); 646240Sigor@sysoev.ru 647240Sigor@sysoev.ru switch (pid) { 648240Sigor@sysoev.ru 649240Sigor@sysoev.ru case -1: 6501565St.nateldemoura@f5.com ret = NXT_ERROR; 6511488St.nateldemoura@f5.com break; 652240Sigor@sysoev.ru 653240Sigor@sysoev.ru case 0: 6541488St.nateldemoura@f5.com /* The child process: return to the event engine work queue loop. */ 6551180Smax.romanov@nginx.com 6561565St.nateldemoura@f5.com nxt_process_use(task, process, -1); 6571565St.nateldemoura@f5.com 6581488St.nateldemoura@f5.com ret = NXT_AGAIN; 6591488St.nateldemoura@f5.com break; 660240Sigor@sysoev.ru 661240Sigor@sysoev.ru default: 662240Sigor@sysoev.ru /* The main process created a new process. */ 663240Sigor@sysoev.ru 6641565St.nateldemoura@f5.com nxt_process_use(task, process, -1); 6651565St.nateldemoura@f5.com 666240Sigor@sysoev.ru nxt_port_read_close(port); 667240Sigor@sysoev.ru nxt_port_write_enable(task, port); 668240Sigor@sysoev.ru 6691488St.nateldemoura@f5.com ret = NXT_OK; 6701488St.nateldemoura@f5.com break; 671240Sigor@sysoev.ru } 672240Sigor@sysoev.ru 6731565St.nateldemoura@f5.com free_mempool: 6741565St.nateldemoura@f5.com 6751565St.nateldemoura@f5.com nxt_mp_destroy(tmp_mp); 6761565St.nateldemoura@f5.com 6771565St.nateldemoura@f5.com close_port: 6781565St.nateldemoura@f5.com 6791565St.nateldemoura@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 6801565St.nateldemoura@f5.com nxt_port_close(task, port); 6811565St.nateldemoura@f5.com } 6821565St.nateldemoura@f5.com 6831565St.nateldemoura@f5.com free_port: 684240Sigor@sysoev.ru 6851488St.nateldemoura@f5.com nxt_port_use(task, port, -1); 686240Sigor@sysoev.ru 6871488St.nateldemoura@f5.com return ret; 688240Sigor@sysoev.ru } 689240Sigor@sysoev.ru 690240Sigor@sysoev.ru 691240Sigor@sysoev.ru static void 692240Sigor@sysoev.ru nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, void *data) 693240Sigor@sysoev.ru { 694240Sigor@sysoev.ru nxt_debug(task, "sigterm handler signo:%d (%s)", 695240Sigor@sysoev.ru (int) (uintptr_t) obj, data); 696240Sigor@sysoev.ru 697240Sigor@sysoev.ru /* TODO: fast exit. */ 698240Sigor@sysoev.ru 699240Sigor@sysoev.ru nxt_exiting = 1; 700240Sigor@sysoev.ru 701697Sigor@sysoev.ru nxt_runtime_quit(task, 0); 702240Sigor@sysoev.ru } 703240Sigor@sysoev.ru 704240Sigor@sysoev.ru 705240Sigor@sysoev.ru static void 706240Sigor@sysoev.ru nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, void *data) 707240Sigor@sysoev.ru { 708240Sigor@sysoev.ru nxt_debug(task, "sigquit handler signo:%d (%s)", 709240Sigor@sysoev.ru (int) (uintptr_t) obj, data); 710240Sigor@sysoev.ru 711240Sigor@sysoev.ru /* TODO: graceful exit. */ 712240Sigor@sysoev.ru 713240Sigor@sysoev.ru nxt_exiting = 1; 714240Sigor@sysoev.ru 715697Sigor@sysoev.ru nxt_runtime_quit(task, 0); 716240Sigor@sysoev.ru } 717240Sigor@sysoev.ru 718240Sigor@sysoev.ru 719240Sigor@sysoev.ru static void 720240Sigor@sysoev.ru nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, void *data) 721240Sigor@sysoev.ru { 722240Sigor@sysoev.ru nxt_mp_t *mp; 723240Sigor@sysoev.ru nxt_int_t ret; 724240Sigor@sysoev.ru nxt_uint_t n; 725631Svbart@nginx.com nxt_port_t *port; 726240Sigor@sysoev.ru nxt_file_t *file, *new_file; 727631Svbart@nginx.com nxt_array_t *new_files; 728240Sigor@sysoev.ru nxt_runtime_t *rt; 729240Sigor@sysoev.ru 730240Sigor@sysoev.ru nxt_log(task, NXT_LOG_NOTICE, "signal %d (%s) recevied, %s", 731240Sigor@sysoev.ru (int) (uintptr_t) obj, data, "log files rotation"); 732240Sigor@sysoev.ru 733631Svbart@nginx.com rt = task->thread->runtime; 734631Svbart@nginx.com 735631Svbart@nginx.com port = rt->port_by_type[NXT_PROCESS_ROUTER]; 736631Svbart@nginx.com 737631Svbart@nginx.com if (nxt_fast_path(port != NULL)) { 738631Svbart@nginx.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_ACCESS_LOG, 739631Svbart@nginx.com -1, 0, 0, NULL); 740631Svbart@nginx.com } 741631Svbart@nginx.com 742240Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 743240Sigor@sysoev.ru if (mp == NULL) { 744240Sigor@sysoev.ru return; 745240Sigor@sysoev.ru } 746240Sigor@sysoev.ru 747240Sigor@sysoev.ru n = nxt_list_nelts(rt->log_files); 748240Sigor@sysoev.ru 749240Sigor@sysoev.ru new_files = nxt_array_create(mp, n, sizeof(nxt_file_t)); 750240Sigor@sysoev.ru if (new_files == NULL) { 751240Sigor@sysoev.ru nxt_mp_destroy(mp); 752240Sigor@sysoev.ru return; 753240Sigor@sysoev.ru } 754240Sigor@sysoev.ru 755240Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 756240Sigor@sysoev.ru 757240Sigor@sysoev.ru /* This allocation cannot fail. */ 758240Sigor@sysoev.ru new_file = nxt_array_add(new_files); 759240Sigor@sysoev.ru 760240Sigor@sysoev.ru new_file->name = file->name; 761240Sigor@sysoev.ru new_file->fd = NXT_FILE_INVALID; 762564Svbart@nginx.com new_file->log_level = NXT_LOG_ALERT; 763240Sigor@sysoev.ru 764240Sigor@sysoev.ru ret = nxt_file_open(task, new_file, O_WRONLY | O_APPEND, O_CREAT, 765240Sigor@sysoev.ru NXT_FILE_OWNER_ACCESS); 766240Sigor@sysoev.ru 767240Sigor@sysoev.ru if (ret != NXT_OK) { 768240Sigor@sysoev.ru goto fail; 769240Sigor@sysoev.ru } 770240Sigor@sysoev.ru 771240Sigor@sysoev.ru } nxt_list_loop; 772240Sigor@sysoev.ru 773240Sigor@sysoev.ru new_file = new_files->elts; 774240Sigor@sysoev.ru 775240Sigor@sysoev.ru ret = nxt_file_stderr(&new_file[0]); 776240Sigor@sysoev.ru 777240Sigor@sysoev.ru if (ret == NXT_OK) { 778240Sigor@sysoev.ru n = 0; 779240Sigor@sysoev.ru 780240Sigor@sysoev.ru nxt_list_each(file, rt->log_files) { 781240Sigor@sysoev.ru 782240Sigor@sysoev.ru nxt_port_change_log_file(task, rt, n, new_file[n].fd); 783240Sigor@sysoev.ru /* 784240Sigor@sysoev.ru * The old log file descriptor must be closed at the moment 785240Sigor@sysoev.ru * when no other threads use it. dup2() allows to use the 786240Sigor@sysoev.ru * old file descriptor for new log file. This change is 787240Sigor@sysoev.ru * performed atomically in the kernel. 788240Sigor@sysoev.ru */ 789240Sigor@sysoev.ru (void) nxt_file_redirect(file, new_file[n].fd); 790240Sigor@sysoev.ru 791240Sigor@sysoev.ru n++; 792240Sigor@sysoev.ru 793240Sigor@sysoev.ru } nxt_list_loop; 794240Sigor@sysoev.ru 795240Sigor@sysoev.ru nxt_mp_destroy(mp); 796240Sigor@sysoev.ru return; 7971008Szelenkov@nginx.com } 798240Sigor@sysoev.ru 799240Sigor@sysoev.ru fail: 800240Sigor@sysoev.ru 801240Sigor@sysoev.ru new_file = new_files->elts; 802240Sigor@sysoev.ru n = new_files->nelts; 803240Sigor@sysoev.ru 804240Sigor@sysoev.ru while (n != 0) { 805240Sigor@sysoev.ru if (new_file->fd != NXT_FILE_INVALID) { 806240Sigor@sysoev.ru nxt_file_close(task, new_file); 807240Sigor@sysoev.ru } 808240Sigor@sysoev.ru 809240Sigor@sysoev.ru new_file++; 810240Sigor@sysoev.ru n--; 811240Sigor@sysoev.ru } 812240Sigor@sysoev.ru 813240Sigor@sysoev.ru nxt_mp_destroy(mp); 814240Sigor@sysoev.ru } 815240Sigor@sysoev.ru 816240Sigor@sysoev.ru 817240Sigor@sysoev.ru static void 818240Sigor@sysoev.ru nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, void *data) 819240Sigor@sysoev.ru { 820240Sigor@sysoev.ru int status; 821240Sigor@sysoev.ru nxt_err_t err; 822240Sigor@sysoev.ru nxt_pid_t pid; 823240Sigor@sysoev.ru 824240Sigor@sysoev.ru nxt_debug(task, "sigchld handler signo:%d (%s)", 825240Sigor@sysoev.ru (int) (uintptr_t) obj, data); 826240Sigor@sysoev.ru 827240Sigor@sysoev.ru for ( ;; ) { 828240Sigor@sysoev.ru pid = waitpid(-1, &status, WNOHANG); 829240Sigor@sysoev.ru 830240Sigor@sysoev.ru if (pid == -1) { 831240Sigor@sysoev.ru 832240Sigor@sysoev.ru switch (err = nxt_errno) { 833240Sigor@sysoev.ru 834240Sigor@sysoev.ru case NXT_ECHILD: 835240Sigor@sysoev.ru return; 836240Sigor@sysoev.ru 837240Sigor@sysoev.ru case NXT_EINTR: 838240Sigor@sysoev.ru continue; 839240Sigor@sysoev.ru 840240Sigor@sysoev.ru default: 841564Svbart@nginx.com nxt_alert(task, "waitpid() failed: %E", err); 842240Sigor@sysoev.ru return; 843240Sigor@sysoev.ru } 844240Sigor@sysoev.ru } 845240Sigor@sysoev.ru 846240Sigor@sysoev.ru nxt_debug(task, "waitpid(): %PI", pid); 847240Sigor@sysoev.ru 848240Sigor@sysoev.ru if (pid == 0) { 849240Sigor@sysoev.ru return; 850240Sigor@sysoev.ru } 851240Sigor@sysoev.ru 852240Sigor@sysoev.ru if (WTERMSIG(status)) { 853240Sigor@sysoev.ru #ifdef WCOREDUMP 854564Svbart@nginx.com nxt_alert(task, "process %PI exited on signal %d%s", 855564Svbart@nginx.com pid, WTERMSIG(status), 856564Svbart@nginx.com WCOREDUMP(status) ? " (core dumped)" : ""); 857240Sigor@sysoev.ru #else 858564Svbart@nginx.com nxt_alert(task, "process %PI exited on signal %d", 859564Svbart@nginx.com pid, WTERMSIG(status)); 860240Sigor@sysoev.ru #endif 861240Sigor@sysoev.ru 862240Sigor@sysoev.ru } else { 863240Sigor@sysoev.ru nxt_trace(task, "process %PI exited with code %d", 864240Sigor@sysoev.ru pid, WEXITSTATUS(status)); 865240Sigor@sysoev.ru } 866240Sigor@sysoev.ru 8671488St.nateldemoura@f5.com nxt_main_cleanup_process(task, pid); 868240Sigor@sysoev.ru } 869240Sigor@sysoev.ru } 870240Sigor@sysoev.ru 871240Sigor@sysoev.ru 872240Sigor@sysoev.ru static void 873944Sigor@sysoev.ru nxt_main_process_signal_handler(nxt_task_t *task, void *obj, void *data) 874944Sigor@sysoev.ru { 875944Sigor@sysoev.ru nxt_trace(task, "signal signo:%d (%s) recevied, ignored", 876944Sigor@sysoev.ru (int) (uintptr_t) obj, data); 877944Sigor@sysoev.ru } 878944Sigor@sysoev.ru 879944Sigor@sysoev.ru 880944Sigor@sysoev.ru static void 8811488St.nateldemoura@f5.com nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid) 882240Sigor@sysoev.ru { 8831488St.nateldemoura@f5.com int stream; 8841488St.nateldemoura@f5.com nxt_int_t ret; 8851488St.nateldemoura@f5.com nxt_buf_t *buf; 8861488St.nateldemoura@f5.com nxt_port_t *port; 8871488St.nateldemoura@f5.com const char *name; 8881488St.nateldemoura@f5.com nxt_runtime_t *rt; 8891488St.nateldemoura@f5.com nxt_process_t *process; 8901488St.nateldemoura@f5.com nxt_process_init_t init; 891240Sigor@sysoev.ru 892240Sigor@sysoev.ru rt = task->thread->runtime; 893240Sigor@sysoev.ru 894240Sigor@sysoev.ru process = nxt_runtime_process_find(rt, pid); 8951488St.nateldemoura@f5.com if (!process) { 8961488St.nateldemoura@f5.com return; 8971488St.nateldemoura@f5.com } 898240Sigor@sysoev.ru 8991579St.nateldemoura@f5.com if (process->isolation.cleanup != NULL) { 9001579St.nateldemoura@f5.com process->isolation.cleanup(task, process); 9011489St.nateldemoura@f5.com } 9021489St.nateldemoura@f5.com 9031488St.nateldemoura@f5.com name = process->name; 9041488St.nateldemoura@f5.com stream = process->stream; 9051488St.nateldemoura@f5.com init = *((nxt_process_init_t *) nxt_process_init(process)); 906366Smax.romanov@nginx.com 9071488St.nateldemoura@f5.com if (process->state == NXT_PROCESS_STATE_READY) { 9081488St.nateldemoura@f5.com process->stream = 0; 9091488St.nateldemoura@f5.com } 910240Sigor@sysoev.ru 9111488St.nateldemoura@f5.com nxt_process_close_ports(task, process); 9121302St.nateldemoura@f5.com 9131488St.nateldemoura@f5.com if (nxt_exiting) { 9141488St.nateldemoura@f5.com if (rt->nprocesses <= 1) { 9151488St.nateldemoura@f5.com nxt_runtime_quit(task, 0); 9161211Smax.romanov@nginx.com } 9171211Smax.romanov@nginx.com 9181488St.nateldemoura@f5.com return; 919240Sigor@sysoev.ru } 920754Smax.romanov@nginx.com 921754Smax.romanov@nginx.com nxt_runtime_process_each(rt, process) { 922754Smax.romanov@nginx.com 9231488St.nateldemoura@f5.com if (process->pid == nxt_pid 9241488St.nateldemoura@f5.com || process->pid == pid 9251488St.nateldemoura@f5.com || nxt_queue_is_empty(&process->ports)) 9261488St.nateldemoura@f5.com { 9271488St.nateldemoura@f5.com continue; 9281488St.nateldemoura@f5.com } 9291488St.nateldemoura@f5.com 9301488St.nateldemoura@f5.com port = nxt_process_port_first(process); 931754Smax.romanov@nginx.com 9321488St.nateldemoura@f5.com if (nxt_proc_remove_notify_matrix[init.type][port->type] == 0) { 9331488St.nateldemoura@f5.com continue; 9341488St.nateldemoura@f5.com } 9351488St.nateldemoura@f5.com 9361488St.nateldemoura@f5.com buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 9371488St.nateldemoura@f5.com sizeof(pid)); 938754Smax.romanov@nginx.com 9391488St.nateldemoura@f5.com if (nxt_slow_path(buf == NULL)) { 9401488St.nateldemoura@f5.com continue; 9411488St.nateldemoura@f5.com } 9421488St.nateldemoura@f5.com 9431488St.nateldemoura@f5.com buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid)); 9441488St.nateldemoura@f5.com 9451488St.nateldemoura@f5.com nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID, -1, 9461488St.nateldemoura@f5.com stream, 0, buf); 947754Smax.romanov@nginx.com 948754Smax.romanov@nginx.com } nxt_runtime_process_loop; 9491488St.nateldemoura@f5.com 9501488St.nateldemoura@f5.com if (init.restart) { 9511488St.nateldemoura@f5.com ret = nxt_main_process_create(task, init); 9521488St.nateldemoura@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 9531488St.nateldemoura@f5.com nxt_alert(task, "failed to restart %s", name); 9541488St.nateldemoura@f5.com } 9551488St.nateldemoura@f5.com } 956754Smax.romanov@nginx.com } 957754Smax.romanov@nginx.com 958754Smax.romanov@nginx.com 959754Smax.romanov@nginx.com static void 960240Sigor@sysoev.ru nxt_main_port_socket_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 961240Sigor@sysoev.ru { 962240Sigor@sysoev.ru size_t size; 963240Sigor@sysoev.ru nxt_int_t ret; 964240Sigor@sysoev.ru nxt_buf_t *b, *out; 965240Sigor@sysoev.ru nxt_port_t *port; 966240Sigor@sysoev.ru nxt_sockaddr_t *sa; 967240Sigor@sysoev.ru nxt_port_msg_type_t type; 968240Sigor@sysoev.ru nxt_listening_socket_t ls; 969240Sigor@sysoev.ru u_char message[2048]; 970240Sigor@sysoev.ru 971240Sigor@sysoev.ru b = msg->buf; 972240Sigor@sysoev.ru sa = (nxt_sockaddr_t *) b->mem.pos; 973240Sigor@sysoev.ru 974352Smax.romanov@nginx.com /* TODO check b size and make plain */ 975352Smax.romanov@nginx.com 976240Sigor@sysoev.ru out = NULL; 977240Sigor@sysoev.ru 978240Sigor@sysoev.ru ls.socket = -1; 979240Sigor@sysoev.ru ls.error = NXT_SOCKET_ERROR_SYSTEM; 980240Sigor@sysoev.ru ls.start = message; 981240Sigor@sysoev.ru ls.end = message + sizeof(message); 982240Sigor@sysoev.ru 983240Sigor@sysoev.ru port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 984240Sigor@sysoev.ru msg->port_msg.reply_port); 985240Sigor@sysoev.ru 986240Sigor@sysoev.ru nxt_debug(task, "listening socket \"%*s\"", 987493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa)); 988240Sigor@sysoev.ru 989240Sigor@sysoev.ru ret = nxt_main_listening_socket(sa, &ls); 990240Sigor@sysoev.ru 991240Sigor@sysoev.ru if (ret == NXT_OK) { 992240Sigor@sysoev.ru nxt_debug(task, "socket(\"%*s\"): %d", 993493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), ls.socket); 994240Sigor@sysoev.ru 995240Sigor@sysoev.ru type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD; 996240Sigor@sysoev.ru 997240Sigor@sysoev.ru } else { 998240Sigor@sysoev.ru size = ls.end - ls.start; 999240Sigor@sysoev.ru 1000564Svbart@nginx.com nxt_alert(task, "%*s", size, ls.start); 1001240Sigor@sysoev.ru 1002342Smax.romanov@nginx.com out = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, 1003342Smax.romanov@nginx.com size + 1); 1004240Sigor@sysoev.ru if (nxt_slow_path(out == NULL)) { 1005240Sigor@sysoev.ru return; 1006240Sigor@sysoev.ru } 1007240Sigor@sysoev.ru 1008240Sigor@sysoev.ru *out->mem.free++ = (uint8_t) ls.error; 1009240Sigor@sysoev.ru 1010240Sigor@sysoev.ru out->mem.free = nxt_cpymem(out->mem.free, ls.start, size); 1011240Sigor@sysoev.ru 1012240Sigor@sysoev.ru type = NXT_PORT_MSG_RPC_ERROR; 1013240Sigor@sysoev.ru } 1014240Sigor@sysoev.ru 1015240Sigor@sysoev.ru nxt_port_socket_write(task, port, type, ls.socket, msg->port_msg.stream, 1016240Sigor@sysoev.ru 0, out); 1017240Sigor@sysoev.ru } 1018240Sigor@sysoev.ru 1019240Sigor@sysoev.ru 1020240Sigor@sysoev.ru static nxt_int_t 1021240Sigor@sysoev.ru nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls) 1022240Sigor@sysoev.ru { 1023240Sigor@sysoev.ru nxt_err_t err; 1024240Sigor@sysoev.ru nxt_socket_t s; 1025240Sigor@sysoev.ru 1026240Sigor@sysoev.ru const socklen_t length = sizeof(int); 1027240Sigor@sysoev.ru static const int enable = 1; 1028240Sigor@sysoev.ru 1029240Sigor@sysoev.ru s = socket(sa->u.sockaddr.sa_family, sa->type, 0); 1030240Sigor@sysoev.ru 1031240Sigor@sysoev.ru if (nxt_slow_path(s == -1)) { 1032240Sigor@sysoev.ru err = nxt_errno; 1033240Sigor@sysoev.ru 1034240Sigor@sysoev.ru #if (NXT_INET6) 1035240Sigor@sysoev.ru 1036240Sigor@sysoev.ru if (err == EAFNOSUPPORT && sa->u.sockaddr.sa_family == AF_INET6) { 1037240Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_NOINET6; 1038240Sigor@sysoev.ru } 1039240Sigor@sysoev.ru 1040240Sigor@sysoev.ru #endif 1041240Sigor@sysoev.ru 1042240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1043240Sigor@sysoev.ru "socket(\\\"%*s\\\") failed %E", 1044493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), err); 1045240Sigor@sysoev.ru 1046240Sigor@sysoev.ru return NXT_ERROR; 1047240Sigor@sysoev.ru } 1048240Sigor@sysoev.ru 1049240Sigor@sysoev.ru if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, length) != 0) { 1050240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1051240Sigor@sysoev.ru "setsockopt(\\\"%*s\\\", SO_REUSEADDR) failed %E", 1052493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), 1053493Spluknet@nginx.com nxt_errno); 1054240Sigor@sysoev.ru goto fail; 1055240Sigor@sysoev.ru } 1056240Sigor@sysoev.ru 1057240Sigor@sysoev.ru #if (NXT_INET6) 1058240Sigor@sysoev.ru 1059240Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_INET6) { 1060240Sigor@sysoev.ru 1061240Sigor@sysoev.ru if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, length) != 0) { 1062240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1063240Sigor@sysoev.ru "setsockopt(\\\"%*s\\\", IPV6_V6ONLY) failed %E", 1064493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), 1065493Spluknet@nginx.com nxt_errno); 1066240Sigor@sysoev.ru goto fail; 1067240Sigor@sysoev.ru } 1068240Sigor@sysoev.ru } 1069240Sigor@sysoev.ru 1070240Sigor@sysoev.ru #endif 1071240Sigor@sysoev.ru 1072240Sigor@sysoev.ru if (bind(s, &sa->u.sockaddr, sa->socklen) != 0) { 1073240Sigor@sysoev.ru err = nxt_errno; 1074240Sigor@sysoev.ru 1075240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 1076240Sigor@sysoev.ru 1077240Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_UNIX) { 1078240Sigor@sysoev.ru switch (err) { 1079240Sigor@sysoev.ru 1080240Sigor@sysoev.ru case EACCES: 1081240Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_ACCESS; 1082240Sigor@sysoev.ru break; 1083240Sigor@sysoev.ru 1084240Sigor@sysoev.ru case ENOENT: 1085240Sigor@sysoev.ru case ENOTDIR: 1086240Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_PATH; 1087240Sigor@sysoev.ru break; 1088240Sigor@sysoev.ru } 1089240Sigor@sysoev.ru 1090908Sigor@sysoev.ru } else 1091908Sigor@sysoev.ru #endif 1092908Sigor@sysoev.ru { 1093908Sigor@sysoev.ru switch (err) { 1094240Sigor@sysoev.ru 1095908Sigor@sysoev.ru case EACCES: 1096908Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_PORT; 1097908Sigor@sysoev.ru break; 1098240Sigor@sysoev.ru 1099908Sigor@sysoev.ru case EADDRINUSE: 1100908Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_INUSE; 1101908Sigor@sysoev.ru break; 1102240Sigor@sysoev.ru 1103908Sigor@sysoev.ru case EADDRNOTAVAIL: 1104908Sigor@sysoev.ru ls->error = NXT_SOCKET_ERROR_NOADDR; 1105908Sigor@sysoev.ru break; 1106908Sigor@sysoev.ru } 1107240Sigor@sysoev.ru } 1108240Sigor@sysoev.ru 1109240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, "bind(\\\"%*s\\\") failed %E", 1110493Spluknet@nginx.com (size_t) sa->length, nxt_sockaddr_start(sa), err); 1111240Sigor@sysoev.ru goto fail; 1112240Sigor@sysoev.ru } 1113240Sigor@sysoev.ru 1114240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN) 1115240Sigor@sysoev.ru 1116240Sigor@sysoev.ru if (sa->u.sockaddr.sa_family == AF_UNIX) { 1117240Sigor@sysoev.ru char *filename; 1118240Sigor@sysoev.ru mode_t access; 1119240Sigor@sysoev.ru 1120240Sigor@sysoev.ru filename = sa->u.sockaddr_un.sun_path; 1121240Sigor@sysoev.ru access = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 1122240Sigor@sysoev.ru 1123240Sigor@sysoev.ru if (chmod(filename, access) != 0) { 1124240Sigor@sysoev.ru ls->end = nxt_sprintf(ls->start, ls->end, 1125494Spluknet@nginx.com "chmod(\\\"%s\\\") failed %E", 1126240Sigor@sysoev.ru filename, nxt_errno); 1127240Sigor@sysoev.ru goto fail; 1128240Sigor@sysoev.ru } 1129240Sigor@sysoev.ru } 1130240Sigor@sysoev.ru 1131240Sigor@sysoev.ru #endif 1132240Sigor@sysoev.ru 1133240Sigor@sysoev.ru ls->socket = s; 1134240Sigor@sysoev.ru 1135240Sigor@sysoev.ru return NXT_OK; 1136240Sigor@sysoev.ru 1137240Sigor@sysoev.ru fail: 1138240Sigor@sysoev.ru 1139240Sigor@sysoev.ru (void) close(s); 1140240Sigor@sysoev.ru 1141240Sigor@sysoev.ru return NXT_ERROR; 1142240Sigor@sysoev.ru } 1143240Sigor@sysoev.ru 1144240Sigor@sysoev.ru 1145240Sigor@sysoev.ru static nxt_conf_map_t nxt_app_lang_module_map[] = { 1146240Sigor@sysoev.ru { 1147240Sigor@sysoev.ru nxt_string("type"), 1148356Svbart@nginx.com NXT_CONF_MAP_INT, 1149240Sigor@sysoev.ru offsetof(nxt_app_lang_module_t, type), 1150240Sigor@sysoev.ru }, 1151240Sigor@sysoev.ru 1152240Sigor@sysoev.ru { 1153240Sigor@sysoev.ru nxt_string("version"), 1154354Svbart@nginx.com NXT_CONF_MAP_CSTRZ, 1155240Sigor@sysoev.ru offsetof(nxt_app_lang_module_t, version), 1156240Sigor@sysoev.ru }, 1157240Sigor@sysoev.ru 1158240Sigor@sysoev.ru { 1159240Sigor@sysoev.ru nxt_string("file"), 1160240Sigor@sysoev.ru NXT_CONF_MAP_CSTRZ, 1161240Sigor@sysoev.ru offsetof(nxt_app_lang_module_t, file), 1162240Sigor@sysoev.ru }, 1163240Sigor@sysoev.ru }; 1164240Sigor@sysoev.ru 1165240Sigor@sysoev.ru 11661489St.nateldemoura@f5.com static nxt_conf_map_t nxt_app_lang_mounts_map[] = { 11671489St.nateldemoura@f5.com { 11681489St.nateldemoura@f5.com nxt_string("src"), 11691489St.nateldemoura@f5.com NXT_CONF_MAP_CSTRZ, 11701489St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, src), 11711489St.nateldemoura@f5.com }, 11721489St.nateldemoura@f5.com { 11731489St.nateldemoura@f5.com nxt_string("dst"), 11741489St.nateldemoura@f5.com NXT_CONF_MAP_CSTRZ, 11751489St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, dst), 11761489St.nateldemoura@f5.com }, 11771489St.nateldemoura@f5.com { 11781673St.nateldemoura@f5.com nxt_string("name"), 11791489St.nateldemoura@f5.com NXT_CONF_MAP_CSTRZ, 11801673St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, name), 11811673St.nateldemoura@f5.com }, 11821673St.nateldemoura@f5.com { 11831673St.nateldemoura@f5.com nxt_string("type"), 11841673St.nateldemoura@f5.com NXT_CONF_MAP_INT, 11851673St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, type), 11861489St.nateldemoura@f5.com }, 11871489St.nateldemoura@f5.com { 11881489St.nateldemoura@f5.com nxt_string("flags"), 11891489St.nateldemoura@f5.com NXT_CONF_MAP_INT, 11901489St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, flags), 11911489St.nateldemoura@f5.com }, 11921489St.nateldemoura@f5.com { 11931489St.nateldemoura@f5.com nxt_string("data"), 11941489St.nateldemoura@f5.com NXT_CONF_MAP_CSTRZ, 11951489St.nateldemoura@f5.com offsetof(nxt_fs_mount_t, data), 11961489St.nateldemoura@f5.com }, 11971489St.nateldemoura@f5.com }; 11981489St.nateldemoura@f5.com 11991489St.nateldemoura@f5.com 1200240Sigor@sysoev.ru static void 1201240Sigor@sysoev.ru nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1202240Sigor@sysoev.ru { 12031489St.nateldemoura@f5.com uint32_t index, jindex, nmounts; 1204240Sigor@sysoev.ru nxt_mp_t *mp; 1205240Sigor@sysoev.ru nxt_int_t ret; 1206240Sigor@sysoev.ru nxt_buf_t *b; 1207549Svbart@nginx.com nxt_port_t *port; 1208240Sigor@sysoev.ru nxt_runtime_t *rt; 12091489St.nateldemoura@f5.com nxt_fs_mount_t *mnt; 12101489St.nateldemoura@f5.com nxt_conf_value_t *conf, *root, *value, *mounts; 1211240Sigor@sysoev.ru nxt_app_lang_module_t *lang; 1212240Sigor@sysoev.ru 12131182St.nateldemoura@f5.com static nxt_str_t root_path = nxt_string("/"); 12141489St.nateldemoura@f5.com static nxt_str_t mounts_name = nxt_string("mounts"); 1215240Sigor@sysoev.ru 1216240Sigor@sysoev.ru rt = task->thread->runtime; 1217240Sigor@sysoev.ru 1218240Sigor@sysoev.ru if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) { 1219240Sigor@sysoev.ru return; 1220240Sigor@sysoev.ru } 1221240Sigor@sysoev.ru 12221211Smax.romanov@nginx.com if (nxt_exiting) { 12231211Smax.romanov@nginx.com nxt_debug(task, "ignoring discovered modules, exiting"); 12241211Smax.romanov@nginx.com return; 12251211Smax.romanov@nginx.com } 12261211Smax.romanov@nginx.com 1227549Svbart@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 1228549Svbart@nginx.com msg->port_msg.reply_port); 1229549Svbart@nginx.com 1230549Svbart@nginx.com if (nxt_fast_path(port != NULL)) { 1231549Svbart@nginx.com (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1, 1232549Svbart@nginx.com msg->port_msg.stream, 0, NULL); 1233549Svbart@nginx.com } 1234549Svbart@nginx.com 1235240Sigor@sysoev.ru b = msg->buf; 1236240Sigor@sysoev.ru 1237240Sigor@sysoev.ru if (b == NULL) { 1238240Sigor@sysoev.ru return; 1239240Sigor@sysoev.ru } 1240240Sigor@sysoev.ru 1241240Sigor@sysoev.ru mp = nxt_mp_create(1024, 128, 256, 32); 1242240Sigor@sysoev.ru if (mp == NULL) { 1243240Sigor@sysoev.ru return; 1244240Sigor@sysoev.ru } 1245240Sigor@sysoev.ru 1246352Smax.romanov@nginx.com b = nxt_buf_chk_make_plain(mp, b, msg->size); 1247352Smax.romanov@nginx.com 1248352Smax.romanov@nginx.com if (b == NULL) { 1249352Smax.romanov@nginx.com return; 1250352Smax.romanov@nginx.com } 1251352Smax.romanov@nginx.com 1252352Smax.romanov@nginx.com nxt_debug(task, "application languages: \"%*s\"", 1253352Smax.romanov@nginx.com b->mem.free - b->mem.pos, b->mem.pos); 1254352Smax.romanov@nginx.com 1255240Sigor@sysoev.ru conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL); 1256240Sigor@sysoev.ru if (conf == NULL) { 1257240Sigor@sysoev.ru goto fail; 1258240Sigor@sysoev.ru } 1259240Sigor@sysoev.ru 1260240Sigor@sysoev.ru root = nxt_conf_get_path(conf, &root_path); 1261240Sigor@sysoev.ru if (root == NULL) { 1262240Sigor@sysoev.ru goto fail; 1263240Sigor@sysoev.ru } 1264240Sigor@sysoev.ru 1265240Sigor@sysoev.ru for (index = 0; /* void */ ; index++) { 1266240Sigor@sysoev.ru value = nxt_conf_get_array_element(root, index); 1267240Sigor@sysoev.ru if (value == NULL) { 1268240Sigor@sysoev.ru break; 1269240Sigor@sysoev.ru } 1270240Sigor@sysoev.ru 12711489St.nateldemoura@f5.com lang = nxt_array_zero_add(rt->languages); 1272240Sigor@sysoev.ru if (lang == NULL) { 1273240Sigor@sysoev.ru goto fail; 1274240Sigor@sysoev.ru } 1275240Sigor@sysoev.ru 1276240Sigor@sysoev.ru lang->module = NULL; 1277240Sigor@sysoev.ru 1278240Sigor@sysoev.ru ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map, 1279240Sigor@sysoev.ru nxt_nitems(nxt_app_lang_module_map), lang); 1280240Sigor@sysoev.ru 1281240Sigor@sysoev.ru if (ret != NXT_OK) { 1282240Sigor@sysoev.ru goto fail; 1283240Sigor@sysoev.ru } 1284240Sigor@sysoev.ru 12851489St.nateldemoura@f5.com mounts = nxt_conf_get_object_member(value, &mounts_name, NULL); 12861489St.nateldemoura@f5.com if (mounts == NULL) { 12871489St.nateldemoura@f5.com nxt_alert(task, "missing mounts from discovery message."); 12881489St.nateldemoura@f5.com goto fail; 12891489St.nateldemoura@f5.com } 12901489St.nateldemoura@f5.com 12911489St.nateldemoura@f5.com if (nxt_conf_type(mounts) != NXT_CONF_ARRAY) { 12921489St.nateldemoura@f5.com nxt_alert(task, "invalid mounts type from discovery message."); 12931489St.nateldemoura@f5.com goto fail; 12941489St.nateldemoura@f5.com } 12951489St.nateldemoura@f5.com 12961489St.nateldemoura@f5.com nmounts = nxt_conf_array_elements_count(mounts); 12971489St.nateldemoura@f5.com 12981489St.nateldemoura@f5.com lang->mounts = nxt_array_create(rt->mem_pool, nmounts, 12991489St.nateldemoura@f5.com sizeof(nxt_fs_mount_t)); 13001489St.nateldemoura@f5.com 13011489St.nateldemoura@f5.com if (lang->mounts == NULL) { 13021489St.nateldemoura@f5.com goto fail; 13031489St.nateldemoura@f5.com } 13041489St.nateldemoura@f5.com 13051489St.nateldemoura@f5.com for (jindex = 0; /* */; jindex++) { 13061489St.nateldemoura@f5.com value = nxt_conf_get_array_element(mounts, jindex); 13071489St.nateldemoura@f5.com if (value == NULL) { 13081489St.nateldemoura@f5.com break; 13091489St.nateldemoura@f5.com } 13101489St.nateldemoura@f5.com 13111489St.nateldemoura@f5.com mnt = nxt_array_zero_add(lang->mounts); 13121489St.nateldemoura@f5.com if (mnt == NULL) { 13131489St.nateldemoura@f5.com goto fail; 13141489St.nateldemoura@f5.com } 13151489St.nateldemoura@f5.com 13161585St.nateldemoura@f5.com mnt->builtin = 1; 13171673St.nateldemoura@f5.com mnt->deps = 1; 13181585St.nateldemoura@f5.com 13191489St.nateldemoura@f5.com ret = nxt_conf_map_object(rt->mem_pool, value, 13201489St.nateldemoura@f5.com nxt_app_lang_mounts_map, 13211489St.nateldemoura@f5.com nxt_nitems(nxt_app_lang_mounts_map), mnt); 13221489St.nateldemoura@f5.com 13231489St.nateldemoura@f5.com if (ret != NXT_OK) { 13241489St.nateldemoura@f5.com goto fail; 13251489St.nateldemoura@f5.com } 13261489St.nateldemoura@f5.com } 13271489St.nateldemoura@f5.com 13281489St.nateldemoura@f5.com nxt_debug(task, "lang %d %s \"%s\" (%d mounts)", 13291489St.nateldemoura@f5.com lang->type, lang->version, lang->file, lang->mounts->nelts); 1330240Sigor@sysoev.ru } 1331240Sigor@sysoev.ru 1332240Sigor@sysoev.ru qsort(rt->languages->elts, rt->languages->nelts, 1333240Sigor@sysoev.ru sizeof(nxt_app_lang_module_t), nxt_app_lang_compare); 1334240Sigor@sysoev.ru 1335240Sigor@sysoev.ru fail: 1336240Sigor@sysoev.ru 1337240Sigor@sysoev.ru nxt_mp_destroy(mp); 1338240Sigor@sysoev.ru 13391488St.nateldemoura@f5.com ret = nxt_main_process_create(task, nxt_controller_process); 13401488St.nateldemoura@f5.com if (ret == NXT_OK) { 13411488St.nateldemoura@f5.com ret = nxt_main_process_create(task, nxt_router_process); 13421488St.nateldemoura@f5.com } 1343240Sigor@sysoev.ru 13441488St.nateldemoura@f5.com if (nxt_slow_path(ret == NXT_ERROR)) { 13451488St.nateldemoura@f5.com nxt_exiting = 1; 13461488St.nateldemoura@f5.com 13471488St.nateldemoura@f5.com nxt_runtime_quit(task, 1); 1348240Sigor@sysoev.ru } 1349240Sigor@sysoev.ru } 1350240Sigor@sysoev.ru 1351240Sigor@sysoev.ru 1352240Sigor@sysoev.ru static int nxt_cdecl 1353240Sigor@sysoev.ru nxt_app_lang_compare(const void *v1, const void *v2) 1354240Sigor@sysoev.ru { 1355240Sigor@sysoev.ru int n; 1356240Sigor@sysoev.ru const nxt_app_lang_module_t *lang1, *lang2; 1357240Sigor@sysoev.ru 1358240Sigor@sysoev.ru lang1 = v1; 1359240Sigor@sysoev.ru lang2 = v2; 1360240Sigor@sysoev.ru 1361356Svbart@nginx.com n = lang1->type - lang2->type; 1362258Sigor@sysoev.ru 1363258Sigor@sysoev.ru if (n != 0) { 1364258Sigor@sysoev.ru return n; 1365258Sigor@sysoev.ru } 1366258Sigor@sysoev.ru 1367354Svbart@nginx.com n = nxt_strverscmp(lang1->version, lang2->version); 1368240Sigor@sysoev.ru 1369240Sigor@sysoev.ru /* Negate result to move higher versions to the beginning. */ 1370240Sigor@sysoev.ru 1371240Sigor@sysoev.ru return -n; 1372240Sigor@sysoev.ru } 1373314Svbart@nginx.com 1374314Svbart@nginx.com 1375314Svbart@nginx.com static void 1376314Svbart@nginx.com nxt_main_port_conf_store_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1377314Svbart@nginx.com { 1378352Smax.romanov@nginx.com ssize_t n, size, offset; 1379314Svbart@nginx.com nxt_buf_t *b; 1380314Svbart@nginx.com nxt_int_t ret; 1381314Svbart@nginx.com nxt_file_t file; 1382314Svbart@nginx.com nxt_runtime_t *rt; 1383314Svbart@nginx.com 1384314Svbart@nginx.com nxt_memzero(&file, sizeof(nxt_file_t)); 1385314Svbart@nginx.com 1386314Svbart@nginx.com rt = task->thread->runtime; 1387314Svbart@nginx.com 1388314Svbart@nginx.com file.name = (nxt_file_name_t *) rt->conf_tmp; 1389314Svbart@nginx.com 1390314Svbart@nginx.com if (nxt_slow_path(nxt_file_open(task, &file, NXT_FILE_WRONLY, 1391314Svbart@nginx.com NXT_FILE_TRUNCATE, NXT_FILE_OWNER_ACCESS) 1392314Svbart@nginx.com != NXT_OK)) 1393314Svbart@nginx.com { 1394314Svbart@nginx.com goto error; 1395314Svbart@nginx.com } 1396314Svbart@nginx.com 1397352Smax.romanov@nginx.com offset = 0; 1398352Smax.romanov@nginx.com 1399314Svbart@nginx.com for (b = msg->buf; b != NULL; b = b->next) { 1400314Svbart@nginx.com size = nxt_buf_mem_used_size(&b->mem); 1401314Svbart@nginx.com 1402352Smax.romanov@nginx.com n = nxt_file_write(&file, b->mem.pos, size, offset); 1403314Svbart@nginx.com 1404314Svbart@nginx.com if (nxt_slow_path(n != size)) { 1405314Svbart@nginx.com nxt_file_close(task, &file); 1406314Svbart@nginx.com (void) nxt_file_delete(file.name); 1407314Svbart@nginx.com goto error; 1408314Svbart@nginx.com } 1409352Smax.romanov@nginx.com 1410352Smax.romanov@nginx.com offset += n; 1411314Svbart@nginx.com } 1412314Svbart@nginx.com 1413314Svbart@nginx.com nxt_file_close(task, &file); 1414314Svbart@nginx.com 1415314Svbart@nginx.com ret = nxt_file_rename(file.name, (nxt_file_name_t *) rt->conf); 1416314Svbart@nginx.com 1417314Svbart@nginx.com if (nxt_fast_path(ret == NXT_OK)) { 1418314Svbart@nginx.com return; 1419314Svbart@nginx.com } 1420314Svbart@nginx.com 1421314Svbart@nginx.com error: 1422314Svbart@nginx.com 1423564Svbart@nginx.com nxt_alert(task, "failed to store current configuration"); 1424314Svbart@nginx.com } 1425630Svbart@nginx.com 1426630Svbart@nginx.com 1427630Svbart@nginx.com static void 1428630Svbart@nginx.com nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) 1429630Svbart@nginx.com { 1430630Svbart@nginx.com u_char *path; 1431630Svbart@nginx.com nxt_int_t ret; 1432630Svbart@nginx.com nxt_file_t file; 1433630Svbart@nginx.com nxt_port_t *port; 1434630Svbart@nginx.com nxt_port_msg_type_t type; 1435630Svbart@nginx.com 1436630Svbart@nginx.com nxt_debug(task, "opening access log file"); 1437630Svbart@nginx.com 1438630Svbart@nginx.com path = msg->buf->mem.pos; 1439630Svbart@nginx.com 1440630Svbart@nginx.com nxt_memzero(&file, sizeof(nxt_file_t)); 1441630Svbart@nginx.com 1442630Svbart@nginx.com file.name = (nxt_file_name_t *) path; 1443630Svbart@nginx.com file.log_level = NXT_LOG_ERR; 1444630Svbart@nginx.com 1445630Svbart@nginx.com ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, 1446630Svbart@nginx.com NXT_FILE_OWNER_ACCESS); 1447630Svbart@nginx.com 1448630Svbart@nginx.com type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD 1449630Svbart@nginx.com : NXT_PORT_MSG_RPC_ERROR; 1450630Svbart@nginx.com 1451630Svbart@nginx.com port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid, 1452630Svbart@nginx.com msg->port_msg.reply_port); 1453630Svbart@nginx.com 1454630Svbart@nginx.com if (nxt_fast_path(port != NULL)) { 1455630Svbart@nginx.com (void) nxt_port_socket_write(task, port, type, file.fd, 1456630Svbart@nginx.com msg->port_msg.stream, 0, NULL); 1457630Svbart@nginx.com } 1458630Svbart@nginx.com } 1459