xref: /unit/src/nxt_application.c (revision 2686:87259ed41698)
10Sigor@sysoev.ru 
20Sigor@sysoev.ru /*
384Smax.romanov@nginx.com  * Copyright (C) Max Romanov
40Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
50Sigor@sysoev.ru  * Copyright (C) Valentin V. Bartenev
60Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
70Sigor@sysoev.ru  */
80Sigor@sysoev.ru 
90Sigor@sysoev.ru #include <nxt_main.h>
1020Sigor@sysoev.ru #include <nxt_runtime.h>
11240Sigor@sysoev.ru #include <nxt_main_process.h>
12431Sigor@sysoev.ru #include <nxt_router.h>
13431Sigor@sysoev.ru #include <nxt_http.h>
14444Sigor@sysoev.ru #include <nxt_application.h>
15743Smax.romanov@nginx.com #include <nxt_unit.h>
16723Smax.romanov@nginx.com #include <nxt_port_memory_int.h>
171579St.nateldemoura@f5.com #include <nxt_isolation.h>
180Sigor@sysoev.ru 
19216Sigor@sysoev.ru #include <glob.h>
200Sigor@sysoev.ru 
211489St.nateldemoura@f5.com #if (NXT_HAVE_PR_SET_NO_NEW_PRIVS)
221489St.nateldemoura@f5.com #include <sys/prctl.h>
231489St.nateldemoura@f5.com #endif
241489St.nateldemoura@f5.com 
25216Sigor@sysoev.ru 
262174Smax.romanov@gmail.com #ifdef WCOREDUMP
272174Smax.romanov@gmail.com #define NXT_WCOREDUMP(s) WCOREDUMP(s)
282174Smax.romanov@gmail.com #else
292174Smax.romanov@gmail.com #define NXT_WCOREDUMP(s) 0
302174Smax.romanov@gmail.com #endif
312174Smax.romanov@gmail.com 
322174Smax.romanov@gmail.com 
33216Sigor@sysoev.ru typedef struct {
34356Svbart@nginx.com     nxt_app_type_t  type;
35356Svbart@nginx.com     nxt_str_t       version;
36356Svbart@nginx.com     nxt_str_t       file;
371489St.nateldemoura@f5.com     nxt_array_t     *mounts;
38216Sigor@sysoev.ru } nxt_module_t;
39216Sigor@sysoev.ru 
40216Sigor@sysoev.ru 
411488St.nateldemoura@f5.com static nxt_int_t nxt_discovery_start(nxt_task_t *task,
421488St.nateldemoura@f5.com     nxt_process_data_t *data);
43216Sigor@sysoev.ru static nxt_buf_t *nxt_discovery_modules(nxt_task_t *task, const char *path);
44216Sigor@sysoev.ru static nxt_int_t nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp,
45216Sigor@sysoev.ru     nxt_array_t *modules, const char *name);
46549Svbart@nginx.com static void nxt_discovery_completion_handler(nxt_task_t *task, void *obj,
47549Svbart@nginx.com     void *data);
48549Svbart@nginx.com static void nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg,
49549Svbart@nginx.com     void *data);
50216Sigor@sysoev.ru static nxt_app_module_t *nxt_app_module_load(nxt_task_t *task,
51216Sigor@sysoev.ru     const char *name);
521998St.nateldemoura@f5.com static nxt_int_t nxt_proto_setup(nxt_task_t *task, nxt_process_t *process);
531998St.nateldemoura@f5.com static nxt_int_t nxt_proto_start(nxt_task_t *task, nxt_process_data_t *data);
541488St.nateldemoura@f5.com static nxt_int_t nxt_app_setup(nxt_task_t *task, nxt_process_t *process);
55678Svbart@nginx.com static nxt_int_t nxt_app_set_environment(nxt_conf_value_t *environment);
561998St.nateldemoura@f5.com static void nxt_proto_start_process_handler(nxt_task_t *task,
571998St.nateldemoura@f5.com     nxt_port_recv_msg_t *msg);
581998St.nateldemoura@f5.com static void nxt_proto_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg);
591998St.nateldemoura@f5.com static void nxt_proto_process_created_handler(nxt_task_t *task,
601998St.nateldemoura@f5.com     nxt_port_recv_msg_t *msg);
611998St.nateldemoura@f5.com static void nxt_proto_quit_children(nxt_task_t *task);
621998St.nateldemoura@f5.com static nxt_process_t *nxt_proto_process_find(nxt_task_t *task, nxt_pid_t pid);
631998St.nateldemoura@f5.com static void nxt_proto_process_add(nxt_task_t *task, nxt_process_t *process);
641998St.nateldemoura@f5.com static nxt_process_t *nxt_proto_process_remove(nxt_task_t *task, nxt_pid_t pid);
651489St.nateldemoura@f5.com static u_char *nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src);
661998St.nateldemoura@f5.com static void nxt_proto_signal_handler(nxt_task_t *task, void *obj, void *data);
671998St.nateldemoura@f5.com static void nxt_proto_sigterm_handler(nxt_task_t *task, void *obj, void *data);
681998St.nateldemoura@f5.com static void nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data);
691489St.nateldemoura@f5.com 
701489St.nateldemoura@f5.com 
711488St.nateldemoura@f5.com nxt_str_t  nxt_server = nxt_string(NXT_SERVER);
720Sigor@sysoev.ru 
73216Sigor@sysoev.ru 
74258Sigor@sysoev.ru static uint32_t  compat[] = {
75360Sigor@sysoev.ru     NXT_VERNUM, NXT_DEBUG,
76258Sigor@sysoev.ru };
77258Sigor@sysoev.ru 
78258Sigor@sysoev.ru 
791998St.nateldemoura@f5.com static nxt_lvlhsh_t           nxt_proto_processes;
801998St.nateldemoura@f5.com static nxt_queue_t            nxt_proto_children;
811998St.nateldemoura@f5.com static nxt_bool_t             nxt_proto_exiting;
821998St.nateldemoura@f5.com 
831998St.nateldemoura@f5.com static nxt_app_module_t       *nxt_app;
841998St.nateldemoura@f5.com static nxt_common_app_conf_t  *nxt_app_conf;
85417Svbart@nginx.com 
86417Svbart@nginx.com 
871488St.nateldemoura@f5.com static const nxt_port_handlers_t  nxt_discovery_process_port_handlers = {
881488St.nateldemoura@f5.com     .quit         = nxt_signal_quit_handler,
891488St.nateldemoura@f5.com     .new_port     = nxt_port_new_port_handler,
901488St.nateldemoura@f5.com     .change_file  = nxt_port_change_log_file_handler,
911488St.nateldemoura@f5.com     .mmap         = nxt_port_mmap_handler,
921488St.nateldemoura@f5.com     .data         = nxt_port_data_handler,
931488St.nateldemoura@f5.com     .remove_pid   = nxt_port_remove_pid_handler,
941488St.nateldemoura@f5.com     .rpc_ready    = nxt_port_rpc_handler,
951488St.nateldemoura@f5.com     .rpc_error    = nxt_port_rpc_handler,
961488St.nateldemoura@f5.com };
971488St.nateldemoura@f5.com 
981488St.nateldemoura@f5.com 
991998St.nateldemoura@f5.com const nxt_sig_event_t  nxt_prototype_signals[] = {
1001998St.nateldemoura@f5.com     nxt_event_signal(SIGHUP,  nxt_proto_signal_handler),
1011998St.nateldemoura@f5.com     nxt_event_signal(SIGINT,  nxt_proto_sigterm_handler),
1021998St.nateldemoura@f5.com     nxt_event_signal(SIGQUIT, nxt_proto_sigterm_handler),
1031998St.nateldemoura@f5.com     nxt_event_signal(SIGTERM, nxt_proto_sigterm_handler),
1041998St.nateldemoura@f5.com     nxt_event_signal(SIGCHLD, nxt_proto_sigchld_handler),
1051998St.nateldemoura@f5.com     nxt_event_signal_end,
1061998St.nateldemoura@f5.com };
1071998St.nateldemoura@f5.com 
1081998St.nateldemoura@f5.com 
1091998St.nateldemoura@f5.com static const nxt_port_handlers_t  nxt_proto_process_port_handlers = {
1101998St.nateldemoura@f5.com     .quit            = nxt_proto_quit_handler,
1111998St.nateldemoura@f5.com     .change_file     = nxt_port_change_log_file_handler,
1121998St.nateldemoura@f5.com     .new_port        = nxt_port_new_port_handler,
1131998St.nateldemoura@f5.com     .process_created = nxt_proto_process_created_handler,
1141998St.nateldemoura@f5.com     .process_ready   = nxt_port_process_ready_handler,
1151998St.nateldemoura@f5.com     .remove_pid      = nxt_port_remove_pid_handler,
1161998St.nateldemoura@f5.com     .start_process   = nxt_proto_start_process_handler,
1171998St.nateldemoura@f5.com     .rpc_ready       = nxt_port_rpc_handler,
1181998St.nateldemoura@f5.com     .rpc_error       = nxt_port_rpc_handler,
1191998St.nateldemoura@f5.com };
1201998St.nateldemoura@f5.com 
1211998St.nateldemoura@f5.com 
1221488St.nateldemoura@f5.com static const nxt_port_handlers_t  nxt_app_process_port_handlers = {
1231488St.nateldemoura@f5.com     .quit         = nxt_signal_quit_handler,
1241488St.nateldemoura@f5.com     .rpc_ready    = nxt_port_rpc_handler,
1251488St.nateldemoura@f5.com     .rpc_error    = nxt_port_rpc_handler,
1261488St.nateldemoura@f5.com };
1271488St.nateldemoura@f5.com 
1281488St.nateldemoura@f5.com 
1291488St.nateldemoura@f5.com const nxt_process_init_t  nxt_discovery_process = {
1301488St.nateldemoura@f5.com     .name           = "discovery",
1311488St.nateldemoura@f5.com     .type           = NXT_PROCESS_DISCOVERY,
1321488St.nateldemoura@f5.com     .prefork        = NULL,
1331488St.nateldemoura@f5.com     .restart        = 0,
1341488St.nateldemoura@f5.com     .setup          = nxt_process_core_setup,
1351488St.nateldemoura@f5.com     .start          = nxt_discovery_start,
1361488St.nateldemoura@f5.com     .port_handlers  = &nxt_discovery_process_port_handlers,
1371488St.nateldemoura@f5.com     .signals        = nxt_process_signals,
1381488St.nateldemoura@f5.com };
1391488St.nateldemoura@f5.com 
1401488St.nateldemoura@f5.com 
1411998St.nateldemoura@f5.com const nxt_process_init_t  nxt_proto_process = {
1421998St.nateldemoura@f5.com     .type           = NXT_PROCESS_PROTOTYPE,
1431998St.nateldemoura@f5.com     .prefork        = nxt_isolation_main_prefork,
1441998St.nateldemoura@f5.com     .restart        = 0,
1451998St.nateldemoura@f5.com     .setup          = nxt_proto_setup,
1461998St.nateldemoura@f5.com     .start          = nxt_proto_start,
1471998St.nateldemoura@f5.com     .port_handlers  = &nxt_proto_process_port_handlers,
1481998St.nateldemoura@f5.com     .signals        = nxt_prototype_signals,
1491998St.nateldemoura@f5.com };
1501998St.nateldemoura@f5.com 
1511998St.nateldemoura@f5.com 
1521488St.nateldemoura@f5.com const nxt_process_init_t  nxt_app_process = {
1531488St.nateldemoura@f5.com     .type           = NXT_PROCESS_APP,
1541488St.nateldemoura@f5.com     .setup          = nxt_app_setup,
1551998St.nateldemoura@f5.com     .start          = NULL,
1561998St.nateldemoura@f5.com     .prefork        = NULL,
1571488St.nateldemoura@f5.com     .restart        = 0,
1581488St.nateldemoura@f5.com     .port_handlers  = &nxt_app_process_port_handlers,
1591488St.nateldemoura@f5.com     .signals        = nxt_process_signals,
1601488St.nateldemoura@f5.com };
1611488St.nateldemoura@f5.com 
1621488St.nateldemoura@f5.com 
1631488St.nateldemoura@f5.com static nxt_int_t
nxt_discovery_start(nxt_task_t * task,nxt_process_data_t * data)1641488St.nateldemoura@f5.com nxt_discovery_start(nxt_task_t *task, nxt_process_data_t *data)
165216Sigor@sysoev.ru {
166549Svbart@nginx.com     uint32_t       stream;
167549Svbart@nginx.com     nxt_buf_t      *b;
168549Svbart@nginx.com     nxt_int_t      ret;
169549Svbart@nginx.com     nxt_port_t     *main_port, *discovery_port;
170549Svbart@nginx.com     nxt_runtime_t  *rt;
171216Sigor@sysoev.ru 
1721488St.nateldemoura@f5.com     nxt_log(task, NXT_LOG_INFO, "discovery started");
173216Sigor@sysoev.ru 
174233Sigor@sysoev.ru     rt = task->thread->runtime;
175216Sigor@sysoev.ru 
176233Sigor@sysoev.ru     b = nxt_discovery_modules(task, rt->modules);
177250Sigor@sysoev.ru     if (nxt_slow_path(b == NULL)) {
178549Svbart@nginx.com         return NXT_ERROR;
179250Sigor@sysoev.ru     }
180233Sigor@sysoev.ru 
181240Sigor@sysoev.ru     main_port = rt->port_by_type[NXT_PROCESS_MAIN];
182549Svbart@nginx.com     discovery_port = rt->port_by_type[NXT_PROCESS_DISCOVERY];
183216Sigor@sysoev.ru 
184549Svbart@nginx.com     stream = nxt_port_rpc_register_handler(task, discovery_port,
185549Svbart@nginx.com                                            nxt_discovery_quit,
186549Svbart@nginx.com                                            nxt_discovery_quit,
187549Svbart@nginx.com                                            main_port->pid, NULL);
188549Svbart@nginx.com 
189645Svbart@nginx.com     if (nxt_slow_path(stream == 0)) {
190645Svbart@nginx.com         return NXT_ERROR;
191645Svbart@nginx.com     }
192645Svbart@nginx.com 
193549Svbart@nginx.com     ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_MODULES, -1,
194549Svbart@nginx.com                                 stream, discovery_port->id, b);
195549Svbart@nginx.com 
196549Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
197549Svbart@nginx.com         nxt_port_rpc_cancel(task, discovery_port, stream);
198549Svbart@nginx.com         return NXT_ERROR;
199549Svbart@nginx.com     }
200216Sigor@sysoev.ru 
201216Sigor@sysoev.ru     return NXT_OK;
202216Sigor@sysoev.ru }
203216Sigor@sysoev.ru 
204216Sigor@sysoev.ru 
205216Sigor@sysoev.ru static nxt_buf_t *
nxt_discovery_modules(nxt_task_t * task,const char * path)206216Sigor@sysoev.ru nxt_discovery_modules(nxt_task_t *task, const char *path)
207216Sigor@sysoev.ru {
2081489St.nateldemoura@f5.com     char            *name;
2091489St.nateldemoura@f5.com     u_char          *p, *end;
2101489St.nateldemoura@f5.com     size_t          size;
2111489St.nateldemoura@f5.com     glob_t          glb;
2121489St.nateldemoura@f5.com     nxt_mp_t        *mp;
2131489St.nateldemoura@f5.com     nxt_buf_t       *b;
2141489St.nateldemoura@f5.com     nxt_int_t       ret;
2151489St.nateldemoura@f5.com     nxt_uint_t      i, n, j;
2161489St.nateldemoura@f5.com     nxt_array_t     *modules, *mounts;
2171489St.nateldemoura@f5.com     nxt_module_t    *module;
2181489St.nateldemoura@f5.com     nxt_fs_mount_t  *mnt;
219216Sigor@sysoev.ru 
220216Sigor@sysoev.ru     b = NULL;
221216Sigor@sysoev.ru 
222216Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
223216Sigor@sysoev.ru     if (mp == NULL) {
224216Sigor@sysoev.ru         return b;
225216Sigor@sysoev.ru     }
226216Sigor@sysoev.ru 
227216Sigor@sysoev.ru     ret = glob(path, 0, NULL, &glb);
228216Sigor@sysoev.ru 
229250Sigor@sysoev.ru     n = glb.gl_pathc;
230250Sigor@sysoev.ru 
231250Sigor@sysoev.ru     if (ret != 0) {
232250Sigor@sysoev.ru         nxt_log(task, NXT_LOG_NOTICE,
233250Sigor@sysoev.ru                 "no modules matching: \"%s\" found", path);
234250Sigor@sysoev.ru         n = 0;
235250Sigor@sysoev.ru     }
236216Sigor@sysoev.ru 
237250Sigor@sysoev.ru     modules = nxt_array_create(mp, n, sizeof(nxt_module_t));
238250Sigor@sysoev.ru     if (modules == NULL) {
239250Sigor@sysoev.ru         goto fail;
240250Sigor@sysoev.ru     }
241250Sigor@sysoev.ru 
242250Sigor@sysoev.ru     for (i = 0; i < n; i++) {
243250Sigor@sysoev.ru         name = glb.gl_pathv[i];
244250Sigor@sysoev.ru 
245250Sigor@sysoev.ru         ret = nxt_discovery_module(task, mp, modules, name);
246250Sigor@sysoev.ru         if (ret != NXT_OK) {
247216Sigor@sysoev.ru             goto fail;
248216Sigor@sysoev.ru         }
249250Sigor@sysoev.ru     }
250216Sigor@sysoev.ru 
251703Svbart@nginx.com     size = nxt_length("[]");
252250Sigor@sysoev.ru     module = modules->elts;
253250Sigor@sysoev.ru     n = modules->nelts;
254216Sigor@sysoev.ru 
255250Sigor@sysoev.ru     for (i = 0; i < n; i++) {
256356Svbart@nginx.com         nxt_debug(task, "module: %d %V %V",
257356Svbart@nginx.com                   module[i].type, &module[i].version, &module[i].file);
258216Sigor@sysoev.ru 
259703Svbart@nginx.com         size += nxt_length("{\"type\": ,");
260703Svbart@nginx.com         size += nxt_length(" \"version\": \"\",");
2611489St.nateldemoura@f5.com         size += nxt_length(" \"file\": \"\",");
2621489St.nateldemoura@f5.com         size += nxt_length(" \"mounts\": []},");
263216Sigor@sysoev.ru 
264356Svbart@nginx.com         size += NXT_INT_T_LEN
265250Sigor@sysoev.ru                 + module[i].version.length
266250Sigor@sysoev.ru                 + module[i].file.length;
2671489St.nateldemoura@f5.com 
2681489St.nateldemoura@f5.com         mounts = module[i].mounts;
2691489St.nateldemoura@f5.com 
2701489St.nateldemoura@f5.com         size += mounts->nelts * nxt_length("{\"src\": \"\", \"dst\": \"\", "
2711673St.nateldemoura@f5.com                                             "\"type\": , \"name\": \"\", "
2721673St.nateldemoura@f5.com                                             "\"flags\": , \"data\": \"\"},");
2731489St.nateldemoura@f5.com 
2741489St.nateldemoura@f5.com         mnt = mounts->elts;
2751489St.nateldemoura@f5.com 
2761489St.nateldemoura@f5.com         for (j = 0; j < mounts->nelts; j++) {
2771489St.nateldemoura@f5.com             size += nxt_strlen(mnt[j].src) + nxt_strlen(mnt[j].dst)
2781673St.nateldemoura@f5.com                     + nxt_strlen(mnt[j].name) + (2 * NXT_INT_T_LEN)
2791489St.nateldemoura@f5.com                     + (mnt[j].data == NULL ? 0 : nxt_strlen(mnt[j].data));
2801489St.nateldemoura@f5.com         }
281250Sigor@sysoev.ru     }
282216Sigor@sysoev.ru 
283250Sigor@sysoev.ru     b = nxt_buf_mem_alloc(mp, size, 0);
284250Sigor@sysoev.ru     if (b == NULL) {
285250Sigor@sysoev.ru         goto fail;
286250Sigor@sysoev.ru     }
287216Sigor@sysoev.ru 
288250Sigor@sysoev.ru     b->completion_handler = nxt_discovery_completion_handler;
289216Sigor@sysoev.ru 
290250Sigor@sysoev.ru     p = b->mem.free;
291250Sigor@sysoev.ru     end = b->mem.end;
292250Sigor@sysoev.ru     *p++ = '[';
293216Sigor@sysoev.ru 
294250Sigor@sysoev.ru     for (i = 0; i < n; i++) {
2951489St.nateldemoura@f5.com         mounts = module[i].mounts;
2961489St.nateldemoura@f5.com 
2971489St.nateldemoura@f5.com         p = nxt_sprintf(p, end, "{\"type\": %d, \"version\": \"%V\", "
2981489St.nateldemoura@f5.com                         "\"file\": \"%V\", \"mounts\": [",
2991489St.nateldemoura@f5.com                         module[i].type, &module[i].version, &module[i].file);
3001489St.nateldemoura@f5.com 
3011489St.nateldemoura@f5.com         mnt = mounts->elts;
3021489St.nateldemoura@f5.com         for (j = 0; j < mounts->nelts; j++) {
3031489St.nateldemoura@f5.com             p = nxt_sprintf(p, end,
3041489St.nateldemoura@f5.com                             "{\"src\": \"%s\", \"dst\": \"%s\", "
3051673St.nateldemoura@f5.com                             "\"name\": \"%s\", \"type\": %d, \"flags\": %d, "
3061489St.nateldemoura@f5.com                             "\"data\": \"%s\"},",
3071673St.nateldemoura@f5.com                             mnt[j].src, mnt[j].dst, mnt[j].name, mnt[j].type,
3081673St.nateldemoura@f5.com                             mnt[j].flags,
3091489St.nateldemoura@f5.com                             mnt[j].data == NULL ? (u_char *) "" : mnt[j].data);
3101489St.nateldemoura@f5.com         }
3111489St.nateldemoura@f5.com 
3121489St.nateldemoura@f5.com         *p++ = ']';
3131489St.nateldemoura@f5.com         *p++ = '}';
3141489St.nateldemoura@f5.com         *p++ = ',';
315250Sigor@sysoev.ru     }
316216Sigor@sysoev.ru 
317250Sigor@sysoev.ru     *p++ = ']';
3181489St.nateldemoura@f5.com 
3191515Smax.romanov@nginx.com     if (nxt_slow_path(p > end)) {
3201489St.nateldemoura@f5.com         nxt_alert(task, "discovery write past the buffer");
3211489St.nateldemoura@f5.com         goto fail;
3221489St.nateldemoura@f5.com     }
3231489St.nateldemoura@f5.com 
324250Sigor@sysoev.ru     b->mem.free = p;
325216Sigor@sysoev.ru 
326216Sigor@sysoev.ru fail:
327216Sigor@sysoev.ru 
328216Sigor@sysoev.ru     globfree(&glb);
329216Sigor@sysoev.ru 
330216Sigor@sysoev.ru     return b;
331216Sigor@sysoev.ru }
332216Sigor@sysoev.ru 
333216Sigor@sysoev.ru 
334216Sigor@sysoev.ru static nxt_int_t
nxt_discovery_module(nxt_task_t * task,nxt_mp_t * mp,nxt_array_t * modules,const char * name)335216Sigor@sysoev.ru nxt_discovery_module(nxt_task_t *task, nxt_mp_t *mp, nxt_array_t *modules,
336216Sigor@sysoev.ru     const char *name)
337216Sigor@sysoev.ru {
3381489St.nateldemoura@f5.com     void                  *dl;
3391489St.nateldemoura@f5.com     nxt_str_t             version;
3401489St.nateldemoura@f5.com     nxt_int_t             ret;
3411489St.nateldemoura@f5.com     nxt_uint_t            i, j, n;
3421489St.nateldemoura@f5.com     nxt_array_t           *mounts;
3431489St.nateldemoura@f5.com     nxt_module_t          *module;
3441489St.nateldemoura@f5.com     nxt_app_type_t        type;
3451489St.nateldemoura@f5.com     nxt_fs_mount_t        *to;
3461489St.nateldemoura@f5.com     nxt_app_module_t      *app;
3471489St.nateldemoura@f5.com     const nxt_fs_mount_t  *from;
348216Sigor@sysoev.ru 
349216Sigor@sysoev.ru     /*
350216Sigor@sysoev.ru      * Only memory allocation failure should return NXT_ERROR.
351216Sigor@sysoev.ru      * Any module processing errors are ignored.
352216Sigor@sysoev.ru      */
353216Sigor@sysoev.ru     ret = NXT_ERROR;
354216Sigor@sysoev.ru 
355216Sigor@sysoev.ru     dl = dlopen(name, RTLD_GLOBAL | RTLD_NOW);
356216Sigor@sysoev.ru 
357216Sigor@sysoev.ru     if (dl == NULL) {
358564Svbart@nginx.com         nxt_alert(task, "dlopen(\"%s\"), failed: \"%s\"", name, dlerror());
359216Sigor@sysoev.ru         return NXT_OK;
360216Sigor@sysoev.ru     }
361216Sigor@sysoev.ru 
362216Sigor@sysoev.ru     app = dlsym(dl, "nxt_app_module");
363216Sigor@sysoev.ru 
364216Sigor@sysoev.ru     if (app != NULL) {
365612Salexander.borisov@nginx.com         nxt_log(task, NXT_LOG_NOTICE, "module: %V %s \"%s\"",
366612Salexander.borisov@nginx.com                 &app->type, app->version, name);
367258Sigor@sysoev.ru 
368258Sigor@sysoev.ru         if (app->compat_length != sizeof(compat)
3692231Salx@nginx.com             || memcmp(app->compat, compat, sizeof(compat)) != 0)
370258Sigor@sysoev.ru         {
371258Sigor@sysoev.ru             nxt_log(task, NXT_LOG_NOTICE, "incompatible module %s", name);
372258Sigor@sysoev.ru 
373258Sigor@sysoev.ru             goto done;
374258Sigor@sysoev.ru         }
375216Sigor@sysoev.ru 
376356Svbart@nginx.com         type = nxt_app_parse_type(app->type.start, app->type.length);
377356Svbart@nginx.com 
378356Svbart@nginx.com         if (type == NXT_APP_UNKNOWN) {
379494Spluknet@nginx.com             nxt_log(task, NXT_LOG_NOTICE, "unknown module type %V", &app->type);
380356Svbart@nginx.com 
381356Svbart@nginx.com             goto done;
382356Svbart@nginx.com         }
383356Svbart@nginx.com 
384216Sigor@sysoev.ru         module = modules->elts;
385216Sigor@sysoev.ru         n = modules->nelts;
386216Sigor@sysoev.ru 
387612Salexander.borisov@nginx.com         version.start = (u_char *) app->version;
388612Salexander.borisov@nginx.com         version.length = nxt_strlen(app->version);
389612Salexander.borisov@nginx.com 
390216Sigor@sysoev.ru         for (i = 0; i < n; i++) {
391356Svbart@nginx.com             if (type == module[i].type
392612Salexander.borisov@nginx.com                 && nxt_strstr_eq(&module[i].version, &version))
393258Sigor@sysoev.ru             {
394216Sigor@sysoev.ru                 nxt_log(task, NXT_LOG_NOTICE,
395216Sigor@sysoev.ru                         "ignoring %s module with the same "
396267Sigor@sysoev.ru                         "application language version %V %V as in %V",
397655Svbart@nginx.com                         name, &app->type, &version, &module[i].file);
398216Sigor@sysoev.ru 
399216Sigor@sysoev.ru                 goto done;
400216Sigor@sysoev.ru             }
401216Sigor@sysoev.ru         }
402216Sigor@sysoev.ru 
403216Sigor@sysoev.ru         module = nxt_array_add(modules);
404216Sigor@sysoev.ru         if (module == NULL) {
405216Sigor@sysoev.ru             goto fail;
406216Sigor@sysoev.ru         }
407216Sigor@sysoev.ru 
408356Svbart@nginx.com         module->type = type;
409216Sigor@sysoev.ru 
410612Salexander.borisov@nginx.com         nxt_str_dup(mp, &module->version, &version);
411612Salexander.borisov@nginx.com         if (module->version.start == NULL) {
412216Sigor@sysoev.ru             goto fail;
413216Sigor@sysoev.ru         }
414216Sigor@sysoev.ru 
415216Sigor@sysoev.ru         module->file.length = nxt_strlen(name);
416216Sigor@sysoev.ru 
417216Sigor@sysoev.ru         module->file.start = nxt_mp_alloc(mp, module->file.length);
418216Sigor@sysoev.ru         if (module->file.start == NULL) {
419216Sigor@sysoev.ru             goto fail;
420216Sigor@sysoev.ru         }
421216Sigor@sysoev.ru 
422216Sigor@sysoev.ru         nxt_memcpy(module->file.start, name, module->file.length);
423216Sigor@sysoev.ru 
4241489St.nateldemoura@f5.com         module->mounts = nxt_array_create(mp, app->nmounts,
4251489St.nateldemoura@f5.com                                           sizeof(nxt_fs_mount_t));
4261489St.nateldemoura@f5.com 
4271489St.nateldemoura@f5.com         if (nxt_slow_path(module->mounts == NULL)) {
4281489St.nateldemoura@f5.com             goto fail;
4291489St.nateldemoura@f5.com         }
4301489St.nateldemoura@f5.com 
4311489St.nateldemoura@f5.com         mounts = module->mounts;
4321489St.nateldemoura@f5.com 
4331489St.nateldemoura@f5.com         for (j = 0; j < app->nmounts; j++) {
4341489St.nateldemoura@f5.com             from = &app->mounts[j];
4351489St.nateldemoura@f5.com             to = nxt_array_zero_add(mounts);
4361489St.nateldemoura@f5.com             if (nxt_slow_path(to == NULL)) {
4371489St.nateldemoura@f5.com                 goto fail;
4381489St.nateldemoura@f5.com             }
4391489St.nateldemoura@f5.com 
4401489St.nateldemoura@f5.com             to->src = nxt_cstr_dup(mp, to->src, from->src);
4411489St.nateldemoura@f5.com             if (nxt_slow_path(to->src == NULL)) {
4421489St.nateldemoura@f5.com                 goto fail;
4431489St.nateldemoura@f5.com             }
4441489St.nateldemoura@f5.com 
4451489St.nateldemoura@f5.com             to->dst = nxt_cstr_dup(mp, to->dst, from->dst);
4461489St.nateldemoura@f5.com             if (nxt_slow_path(to->dst == NULL)) {
4471489St.nateldemoura@f5.com                 goto fail;
4481489St.nateldemoura@f5.com             }
4491489St.nateldemoura@f5.com 
4501673St.nateldemoura@f5.com             to->name = nxt_cstr_dup(mp, to->name, from->name);
4511673St.nateldemoura@f5.com             if (nxt_slow_path(to->name == NULL)) {
4521489St.nateldemoura@f5.com                 goto fail;
4531489St.nateldemoura@f5.com             }
4541489St.nateldemoura@f5.com 
4551673St.nateldemoura@f5.com             to->type = from->type;
4561673St.nateldemoura@f5.com 
4571489St.nateldemoura@f5.com             if (from->data != NULL) {
4581489St.nateldemoura@f5.com                 to->data = nxt_cstr_dup(mp, to->data, from->data);
4591489St.nateldemoura@f5.com                 if (nxt_slow_path(to->data == NULL)) {
4601489St.nateldemoura@f5.com                     goto fail;
4611489St.nateldemoura@f5.com                 }
4621489St.nateldemoura@f5.com             }
4631489St.nateldemoura@f5.com 
4641489St.nateldemoura@f5.com             to->flags = from->flags;
4651489St.nateldemoura@f5.com         }
4661489St.nateldemoura@f5.com 
467216Sigor@sysoev.ru     } else {
468564Svbart@nginx.com         nxt_alert(task, "dlsym(\"%s\"), failed: \"%s\"", name, dlerror());
469216Sigor@sysoev.ru     }
470216Sigor@sysoev.ru 
471216Sigor@sysoev.ru done:
472216Sigor@sysoev.ru 
473216Sigor@sysoev.ru     ret = NXT_OK;
474216Sigor@sysoev.ru 
475216Sigor@sysoev.ru fail:
476216Sigor@sysoev.ru 
477216Sigor@sysoev.ru     if (dlclose(dl) != 0) {
478564Svbart@nginx.com         nxt_alert(task, "dlclose(\"%s\"), failed: \"%s\"", name, dlerror());
479216Sigor@sysoev.ru     }
480216Sigor@sysoev.ru 
481216Sigor@sysoev.ru     return ret;
482216Sigor@sysoev.ru }
483216Sigor@sysoev.ru 
484216Sigor@sysoev.ru 
485549Svbart@nginx.com static void
nxt_discovery_completion_handler(nxt_task_t * task,void * obj,void * data)486549Svbart@nginx.com nxt_discovery_completion_handler(nxt_task_t *task, void *obj, void *data)
487549Svbart@nginx.com {
488549Svbart@nginx.com     nxt_mp_t   *mp;
489549Svbart@nginx.com     nxt_buf_t  *b;
490549Svbart@nginx.com 
491549Svbart@nginx.com     b = obj;
492549Svbart@nginx.com     mp = b->data;
493549Svbart@nginx.com 
494549Svbart@nginx.com     nxt_mp_destroy(mp);
495549Svbart@nginx.com }
496549Svbart@nginx.com 
497549Svbart@nginx.com 
498549Svbart@nginx.com static void
nxt_discovery_quit(nxt_task_t * task,nxt_port_recv_msg_t * msg,void * data)499549Svbart@nginx.com nxt_discovery_quit(nxt_task_t *task, nxt_port_recv_msg_t *msg, void *data)
500549Svbart@nginx.com {
5011488St.nateldemoura@f5.com     nxt_signal_quit_handler(task, msg);
502549Svbart@nginx.com }
503549Svbart@nginx.com 
504549Svbart@nginx.com 
5051488St.nateldemoura@f5.com static nxt_int_t
nxt_proto_setup(nxt_task_t * task,nxt_process_t * process)5061998St.nateldemoura@f5.com nxt_proto_setup(nxt_task_t *task, nxt_process_t *process)
5070Sigor@sysoev.ru {
508216Sigor@sysoev.ru     nxt_int_t              ret;
509216Sigor@sysoev.ru     nxt_app_lang_module_t  *lang;
510216Sigor@sysoev.ru     nxt_common_app_conf_t  *app_conf;
511141Smax.romanov@nginx.com 
5121488St.nateldemoura@f5.com     app_conf = process->data.app;
513141Smax.romanov@nginx.com 
5141998St.nateldemoura@f5.com     nxt_queue_init(&nxt_proto_children);
5151998St.nateldemoura@f5.com 
5161998St.nateldemoura@f5.com     nxt_app_conf = app_conf;
5171998St.nateldemoura@f5.com 
518216Sigor@sysoev.ru     lang = nxt_app_lang_module(task->thread->runtime, &app_conf->type);
519216Sigor@sysoev.ru     if (nxt_slow_path(lang == NULL)) {
520564Svbart@nginx.com         nxt_alert(task, "unknown application type: \"%V\"", &app_conf->type);
521216Sigor@sysoev.ru         return NXT_ERROR;
522216Sigor@sysoev.ru     }
523216Sigor@sysoev.ru 
524216Sigor@sysoev.ru     nxt_app = lang->module;
525216Sigor@sysoev.ru 
526216Sigor@sysoev.ru     if (nxt_app == NULL) {
527354Svbart@nginx.com         nxt_debug(task, "application language module: %s \"%s\"",
528354Svbart@nginx.com                   lang->version, lang->file);
529216Sigor@sysoev.ru 
530216Sigor@sysoev.ru         nxt_app = nxt_app_module_load(task, lang->file);
5311239Smax.romanov@nginx.com         if (nxt_slow_path(nxt_app == NULL)) {
5321239Smax.romanov@nginx.com             return NXT_ERROR;
5331239Smax.romanov@nginx.com         }
534216Sigor@sysoev.ru     }
535216Sigor@sysoev.ru 
5361489St.nateldemoura@f5.com     if (nxt_slow_path(nxt_app_set_environment(app_conf->environment)
5371489St.nateldemoura@f5.com                       != NXT_OK))
5381489St.nateldemoura@f5.com     {
5391489St.nateldemoura@f5.com         nxt_alert(task, "failed to set environment");
5401489St.nateldemoura@f5.com         return NXT_ERROR;
5411489St.nateldemoura@f5.com     }
5421489St.nateldemoura@f5.com 
5431488St.nateldemoura@f5.com     if (nxt_app->setup != NULL) {
5441488St.nateldemoura@f5.com         ret = nxt_app->setup(task, process, app_conf);
545977Smax.romanov@gmail.com         if (nxt_slow_path(ret != NXT_OK)) {
5461104Smax.romanov@nginx.com             return ret;
547977Smax.romanov@gmail.com         }
548977Smax.romanov@gmail.com     }
549977Smax.romanov@gmail.com 
5501489St.nateldemoura@f5.com #if (NXT_HAVE_ISOLATION_ROOTFS)
5511489St.nateldemoura@f5.com     if (process->isolation.rootfs != NULL) {
5521489St.nateldemoura@f5.com         if (process->isolation.mounts != NULL) {
5531579St.nateldemoura@f5.com             ret = nxt_isolation_prepare_rootfs(task, process);
5541489St.nateldemoura@f5.com             if (nxt_slow_path(ret != NXT_OK)) {
5551489St.nateldemoura@f5.com                 return ret;
5561489St.nateldemoura@f5.com             }
5571489St.nateldemoura@f5.com         }
5581489St.nateldemoura@f5.com 
5591579St.nateldemoura@f5.com         ret = nxt_isolation_change_root(task, process);
5601489St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
5611489St.nateldemoura@f5.com             return NXT_ERROR;
5621489St.nateldemoura@f5.com         }
5631489St.nateldemoura@f5.com     }
5641489St.nateldemoura@f5.com #endif
5651489St.nateldemoura@f5.com 
566277Sigor@sysoev.ru     if (app_conf->working_directory != NULL
567277Sigor@sysoev.ru         && app_conf->working_directory[0] != 0)
568271Smax.romanov@nginx.com     {
569271Smax.romanov@nginx.com         ret = chdir(app_conf->working_directory);
570271Smax.romanov@nginx.com 
571271Smax.romanov@nginx.com         if (nxt_slow_path(ret != 0)) {
572271Smax.romanov@nginx.com             nxt_log(task, NXT_LOG_WARN, "chdir(%s) failed %E",
573271Smax.romanov@nginx.com                     app_conf->working_directory, nxt_errno);
574271Smax.romanov@nginx.com 
575271Smax.romanov@nginx.com             return NXT_ERROR;
576271Smax.romanov@nginx.com         }
577271Smax.romanov@nginx.com     }
578271Smax.romanov@nginx.com 
5791998St.nateldemoura@f5.com     process->state = NXT_PROCESS_STATE_CREATED;
5801998St.nateldemoura@f5.com 
5811998St.nateldemoura@f5.com     return NXT_OK;
5821998St.nateldemoura@f5.com }
5831998St.nateldemoura@f5.com 
5841998St.nateldemoura@f5.com 
5851998St.nateldemoura@f5.com static nxt_int_t
nxt_proto_start(nxt_task_t * task,nxt_process_data_t * data)5861998St.nateldemoura@f5.com nxt_proto_start(nxt_task_t *task, nxt_process_data_t *data)
5871998St.nateldemoura@f5.com {
5881998St.nateldemoura@f5.com     nxt_debug(task, "prototype waiting for clone messages");
5891998St.nateldemoura@f5.com 
5901998St.nateldemoura@f5.com     return NXT_OK;
5911998St.nateldemoura@f5.com }
5921998St.nateldemoura@f5.com 
5931998St.nateldemoura@f5.com 
5941998St.nateldemoura@f5.com static void
nxt_proto_start_process_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)5951998St.nateldemoura@f5.com nxt_proto_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
5961998St.nateldemoura@f5.com {
5971998St.nateldemoura@f5.com     u_char              *p;
5981998St.nateldemoura@f5.com     nxt_int_t           ret;
5991998St.nateldemoura@f5.com     nxt_port_t          *port;
6001998St.nateldemoura@f5.com     nxt_runtime_t       *rt;
6011998St.nateldemoura@f5.com     nxt_process_t       *process;
6021998St.nateldemoura@f5.com     nxt_process_init_t  *init;
6031998St.nateldemoura@f5.com 
6041998St.nateldemoura@f5.com     rt = task->thread->runtime;
6051998St.nateldemoura@f5.com 
6061998St.nateldemoura@f5.com     process = nxt_process_new(rt);
6071998St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
6081998St.nateldemoura@f5.com         goto failed;
6091998St.nateldemoura@f5.com     }
6101998St.nateldemoura@f5.com 
6111998St.nateldemoura@f5.com     process->mem_pool = nxt_mp_create(1024, 128, 256, 32);
6121998St.nateldemoura@f5.com     if (nxt_slow_path(process->mem_pool == NULL)) {
6131998St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6141998St.nateldemoura@f5.com         goto failed;
6151998St.nateldemoura@f5.com     }
6161998St.nateldemoura@f5.com 
6171998St.nateldemoura@f5.com     process->parent_port = rt->port_by_type[NXT_PROCESS_PROTOTYPE];
6181998St.nateldemoura@f5.com 
6191488St.nateldemoura@f5.com     init = nxt_process_init(process);
6201998St.nateldemoura@f5.com     *init = nxt_app_process;
6211998St.nateldemoura@f5.com 
6221998St.nateldemoura@f5.com     process->name = nxt_mp_alloc(process->mem_pool, nxt_app_conf->name.length
6231998St.nateldemoura@f5.com                                  + sizeof("\"\" application") + 1);
6241998St.nateldemoura@f5.com 
6251998St.nateldemoura@f5.com     if (nxt_slow_path(process->name == NULL)) {
6261998St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6271998St.nateldemoura@f5.com 
6281998St.nateldemoura@f5.com         goto failed;
6291998St.nateldemoura@f5.com     }
630141Smax.romanov@nginx.com 
6311488St.nateldemoura@f5.com     init->start = nxt_app->start;
632141Smax.romanov@nginx.com 
6331998St.nateldemoura@f5.com     init->name = (const char *) nxt_app_conf->name.start;
6341998St.nateldemoura@f5.com 
6351998St.nateldemoura@f5.com     p = (u_char *) process->name;
6361998St.nateldemoura@f5.com     *p++ = '"';
6371998St.nateldemoura@f5.com     p = nxt_cpymem(p, nxt_app_conf->name.start, nxt_app_conf->name.length);
6381998St.nateldemoura@f5.com     p = nxt_cpymem(p, "\" application", 13);
6391998St.nateldemoura@f5.com     *p = '\0';
6401998St.nateldemoura@f5.com 
6411998St.nateldemoura@f5.com     process->user_cred = &rt->user_cred;
6421998St.nateldemoura@f5.com 
6431998St.nateldemoura@f5.com     process->data.app = nxt_app_conf;
6441998St.nateldemoura@f5.com     process->stream = msg->port_msg.stream;
6451998St.nateldemoura@f5.com 
6462174Smax.romanov@gmail.com     init->siblings = &nxt_proto_children;
6472174Smax.romanov@gmail.com 
6481998St.nateldemoura@f5.com     ret = nxt_process_start(task, process);
6491998St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
6501998St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6511998St.nateldemoura@f5.com 
6521998St.nateldemoura@f5.com         goto failed;
6531998St.nateldemoura@f5.com     }
6541998St.nateldemoura@f5.com 
6551998St.nateldemoura@f5.com     nxt_proto_process_add(task, process);
6561998St.nateldemoura@f5.com 
6571998St.nateldemoura@f5.com     return;
6581998St.nateldemoura@f5.com 
6591998St.nateldemoura@f5.com failed:
6601998St.nateldemoura@f5.com 
6611998St.nateldemoura@f5.com     port = nxt_runtime_port_find(rt, msg->port_msg.pid,
6621998St.nateldemoura@f5.com                                  msg->port_msg.reply_port);
6631998St.nateldemoura@f5.com 
6641998St.nateldemoura@f5.com     if (nxt_fast_path(port != NULL)) {
6651998St.nateldemoura@f5.com         nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
6661998St.nateldemoura@f5.com                               -1, msg->port_msg.stream, 0, NULL);
6671998St.nateldemoura@f5.com     }
6681998St.nateldemoura@f5.com }
6691998St.nateldemoura@f5.com 
6701998St.nateldemoura@f5.com 
6711998St.nateldemoura@f5.com static void
nxt_proto_quit_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)6721998St.nateldemoura@f5.com nxt_proto_quit_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
6731998St.nateldemoura@f5.com {
6741998St.nateldemoura@f5.com     nxt_debug(task, "prototype quit handler");
6751998St.nateldemoura@f5.com 
6761998St.nateldemoura@f5.com     nxt_proto_quit_children(task);
6771998St.nateldemoura@f5.com 
6781998St.nateldemoura@f5.com     nxt_proto_exiting = 1;
6791998St.nateldemoura@f5.com 
6801998St.nateldemoura@f5.com     if (nxt_queue_is_empty(&nxt_proto_children)) {
6811998St.nateldemoura@f5.com         nxt_process_quit(task, 0);
6821998St.nateldemoura@f5.com     }
6831998St.nateldemoura@f5.com }
6841998St.nateldemoura@f5.com 
6851998St.nateldemoura@f5.com 
6861998St.nateldemoura@f5.com static void
nxt_proto_quit_children(nxt_task_t * task)6871998St.nateldemoura@f5.com nxt_proto_quit_children(nxt_task_t *task)
6881998St.nateldemoura@f5.com {
6891998St.nateldemoura@f5.com     nxt_port_t     *port;
6901998St.nateldemoura@f5.com     nxt_process_t  *process;
6911998St.nateldemoura@f5.com 
6921998St.nateldemoura@f5.com     nxt_queue_each(process, &nxt_proto_children, nxt_process_t, link) {
6931998St.nateldemoura@f5.com         port = nxt_process_port_first(process);
6941998St.nateldemoura@f5.com 
6951998St.nateldemoura@f5.com         (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT,
6961998St.nateldemoura@f5.com                                      -1, 0, 0, NULL);
6971998St.nateldemoura@f5.com     }
6981998St.nateldemoura@f5.com     nxt_queue_loop;
6991998St.nateldemoura@f5.com }
7001998St.nateldemoura@f5.com 
7011998St.nateldemoura@f5.com 
7021998St.nateldemoura@f5.com static void
nxt_proto_process_created_handler(nxt_task_t * task,nxt_port_recv_msg_t * msg)7031998St.nateldemoura@f5.com nxt_proto_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
7041998St.nateldemoura@f5.com {
7051998St.nateldemoura@f5.com     nxt_pid_t      isolated_pid, pid;
7061998St.nateldemoura@f5.com     nxt_process_t  *process;
7071998St.nateldemoura@f5.com 
7081998St.nateldemoura@f5.com     isolated_pid = nxt_recv_msg_cmsg_pid(msg);
7091998St.nateldemoura@f5.com 
7101998St.nateldemoura@f5.com     process = nxt_proto_process_find(task, isolated_pid);
7111998St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
7121998St.nateldemoura@f5.com         return;
7131998St.nateldemoura@f5.com     }
7141998St.nateldemoura@f5.com 
7151488St.nateldemoura@f5.com     process->state = NXT_PROCESS_STATE_CREATED;
71620Sigor@sysoev.ru 
7171998St.nateldemoura@f5.com     pid = msg->port_msg.pid;
7181998St.nateldemoura@f5.com 
7191998St.nateldemoura@f5.com     if (process->pid != pid) {
7201998St.nateldemoura@f5.com         nxt_debug(task, "app process %PI (aka %PI) is created", isolated_pid,
7211998St.nateldemoura@f5.com                   pid);
7221998St.nateldemoura@f5.com 
7232174Smax.romanov@gmail.com         process->pid = pid;
7241998St.nateldemoura@f5.com 
7252174Smax.romanov@gmail.com     } else {
7262174Smax.romanov@gmail.com         nxt_debug(task, "app process %PI is created", isolated_pid);
7272174Smax.romanov@gmail.com     }
7282174Smax.romanov@gmail.com 
7292174Smax.romanov@gmail.com     if (!process->registered) {
7302174Smax.romanov@gmail.com         nxt_assert(!nxt_queue_is_empty(&process->ports));
7311998St.nateldemoura@f5.com 
7321998St.nateldemoura@f5.com         nxt_runtime_process_add(task, process);
7331998St.nateldemoura@f5.com 
7342174Smax.romanov@gmail.com         nxt_port_use(task, nxt_process_port_first(process), -1);
7351998St.nateldemoura@f5.com     }
7361998St.nateldemoura@f5.com }
7371998St.nateldemoura@f5.com 
7381998St.nateldemoura@f5.com 
7391998St.nateldemoura@f5.com static void
nxt_proto_signal_handler(nxt_task_t * task,void * obj,void * data)7401998St.nateldemoura@f5.com nxt_proto_signal_handler(nxt_task_t *task, void *obj, void *data)
7411998St.nateldemoura@f5.com {
7421998St.nateldemoura@f5.com     nxt_trace(task, "signal signo:%d (%s) received, ignored",
7431998St.nateldemoura@f5.com               (int) (uintptr_t) obj, data);
7441998St.nateldemoura@f5.com }
7451998St.nateldemoura@f5.com 
7461998St.nateldemoura@f5.com 
7471998St.nateldemoura@f5.com static void
nxt_proto_sigterm_handler(nxt_task_t * task,void * obj,void * data)7481998St.nateldemoura@f5.com nxt_proto_sigterm_handler(nxt_task_t *task, void *obj, void *data)
7491998St.nateldemoura@f5.com {
7501998St.nateldemoura@f5.com     nxt_trace(task, "signal signo:%d (%s) received",
7511998St.nateldemoura@f5.com               (int) (uintptr_t) obj, data);
7521998St.nateldemoura@f5.com 
7531998St.nateldemoura@f5.com     nxt_proto_quit_children(task);
7541998St.nateldemoura@f5.com 
7551998St.nateldemoura@f5.com     nxt_proto_exiting = 1;
7561998St.nateldemoura@f5.com 
7571998St.nateldemoura@f5.com     if (nxt_queue_is_empty(&nxt_proto_children)) {
7581998St.nateldemoura@f5.com         nxt_process_quit(task, 0);
7591998St.nateldemoura@f5.com     }
7601998St.nateldemoura@f5.com }
7611998St.nateldemoura@f5.com 
7621998St.nateldemoura@f5.com 
7631998St.nateldemoura@f5.com static void
nxt_proto_sigchld_handler(nxt_task_t * task,void * obj,void * data)7641998St.nateldemoura@f5.com nxt_proto_sigchld_handler(nxt_task_t *task, void *obj, void *data)
7651998St.nateldemoura@f5.com {
7661998St.nateldemoura@f5.com     int            status;
7671998St.nateldemoura@f5.com     nxt_err_t      err;
7681998St.nateldemoura@f5.com     nxt_pid_t      pid;
7692174Smax.romanov@gmail.com     nxt_port_t     *port;
7701998St.nateldemoura@f5.com     nxt_process_t  *process;
7712174Smax.romanov@gmail.com     nxt_runtime_t  *rt;
7722174Smax.romanov@gmail.com 
7732174Smax.romanov@gmail.com     rt = task->thread->runtime;
7741998St.nateldemoura@f5.com 
7751998St.nateldemoura@f5.com     nxt_debug(task, "proto sigchld handler signo:%d (%s)",
7761998St.nateldemoura@f5.com               (int) (uintptr_t) obj, data);
7771998St.nateldemoura@f5.com 
7781998St.nateldemoura@f5.com     for ( ;; ) {
7791998St.nateldemoura@f5.com         pid = waitpid(-1, &status, WNOHANG);
7801998St.nateldemoura@f5.com 
7811998St.nateldemoura@f5.com         if (pid == -1) {
7821998St.nateldemoura@f5.com 
7831998St.nateldemoura@f5.com             switch (err = nxt_errno) {
7841998St.nateldemoura@f5.com 
7851998St.nateldemoura@f5.com             case NXT_ECHILD:
7861998St.nateldemoura@f5.com                 return;
7871998St.nateldemoura@f5.com 
7881998St.nateldemoura@f5.com             case NXT_EINTR:
7891998St.nateldemoura@f5.com                 continue;
7901998St.nateldemoura@f5.com 
7911998St.nateldemoura@f5.com             default:
7921998St.nateldemoura@f5.com                 nxt_alert(task, "waitpid() failed: %E", err);
7931998St.nateldemoura@f5.com                 return;
7941998St.nateldemoura@f5.com             }
7951998St.nateldemoura@f5.com         }
7961998St.nateldemoura@f5.com 
7971998St.nateldemoura@f5.com         nxt_debug(task, "waitpid(): %PI", pid);
7981998St.nateldemoura@f5.com 
7991998St.nateldemoura@f5.com         if (pid == 0) {
8001998St.nateldemoura@f5.com             return;
8011998St.nateldemoura@f5.com         }
8021998St.nateldemoura@f5.com 
8032174Smax.romanov@gmail.com         process = nxt_proto_process_remove(task, pid);
8042174Smax.romanov@gmail.com 
8051998St.nateldemoura@f5.com         if (WTERMSIG(status)) {
8062174Smax.romanov@gmail.com             if (rt->is_pid_isolated) {
8072174Smax.romanov@gmail.com                 nxt_alert(task, "app process %PI (isolated %PI) "
8082174Smax.romanov@gmail.com                                 "exited on signal %d%s",
8092174Smax.romanov@gmail.com                           process != NULL ? process->pid : 0,
8102174Smax.romanov@gmail.com                           pid, WTERMSIG(status),
8112174Smax.romanov@gmail.com                           NXT_WCOREDUMP(status) ? " (core dumped)" : "");
8122174Smax.romanov@gmail.com 
8132174Smax.romanov@gmail.com             } else {
8142174Smax.romanov@gmail.com                 nxt_alert(task, "app process %PI exited on signal %d%s",
8152174Smax.romanov@gmail.com                           pid, WTERMSIG(status),
8162174Smax.romanov@gmail.com                           NXT_WCOREDUMP(status) ? " (core dumped)" : "");
8172174Smax.romanov@gmail.com             }
8181998St.nateldemoura@f5.com 
8191998St.nateldemoura@f5.com         } else {
8202174Smax.romanov@gmail.com             if (rt->is_pid_isolated) {
8212174Smax.romanov@gmail.com                 nxt_trace(task, "app process %PI (isolated %PI) "
8222174Smax.romanov@gmail.com                                 "exited with code %d",
8232174Smax.romanov@gmail.com                           process != NULL ? process->pid : 0,
8242174Smax.romanov@gmail.com                           pid, WEXITSTATUS(status));
8252174Smax.romanov@gmail.com 
8262174Smax.romanov@gmail.com             } else {
8272174Smax.romanov@gmail.com                 nxt_trace(task, "app process %PI exited with code %d",
8282174Smax.romanov@gmail.com                           pid, WEXITSTATUS(status));
8292174Smax.romanov@gmail.com             }
8301998St.nateldemoura@f5.com         }
8311998St.nateldemoura@f5.com 
8321998St.nateldemoura@f5.com         if (process == NULL) {
8331998St.nateldemoura@f5.com             continue;
8341998St.nateldemoura@f5.com         }
8351998St.nateldemoura@f5.com 
8362174Smax.romanov@gmail.com         if (process->registered) {
8372174Smax.romanov@gmail.com             port = NULL;
8382174Smax.romanov@gmail.com 
8392174Smax.romanov@gmail.com         } else {
8402174Smax.romanov@gmail.com             nxt_assert(!nxt_queue_is_empty(&process->ports));
8412174Smax.romanov@gmail.com 
8422174Smax.romanov@gmail.com             port = nxt_process_port_first(process);
8432174Smax.romanov@gmail.com         }
8442174Smax.romanov@gmail.com 
8451998St.nateldemoura@f5.com         if (process->state != NXT_PROCESS_STATE_CREATING) {
8461998St.nateldemoura@f5.com             nxt_port_remove_notify_others(task, process);
8471998St.nateldemoura@f5.com         }
8481998St.nateldemoura@f5.com 
8491998St.nateldemoura@f5.com         nxt_process_close_ports(task, process);
8501998St.nateldemoura@f5.com 
8512174Smax.romanov@gmail.com         if (port != NULL) {
8522174Smax.romanov@gmail.com             nxt_port_use(task, port, -1);
8532174Smax.romanov@gmail.com         }
8542174Smax.romanov@gmail.com 
8551998St.nateldemoura@f5.com         if (nxt_proto_exiting && nxt_queue_is_empty(&nxt_proto_children)) {
8561998St.nateldemoura@f5.com             nxt_process_quit(task, 0);
8571998St.nateldemoura@f5.com             return;
8581998St.nateldemoura@f5.com         }
8591998St.nateldemoura@f5.com     }
86020Sigor@sysoev.ru }
86120Sigor@sysoev.ru 
86220Sigor@sysoev.ru 
863216Sigor@sysoev.ru static nxt_app_module_t *
nxt_app_module_load(nxt_task_t * task,const char * name)864216Sigor@sysoev.ru nxt_app_module_load(nxt_task_t *task, const char *name)
865216Sigor@sysoev.ru {
8661983Svbart@nginx.com     char              *err;
8671983Svbart@nginx.com     void              *dl;
8681983Svbart@nginx.com     nxt_app_module_t  *app;
869216Sigor@sysoev.ru 
870216Sigor@sysoev.ru     dl = dlopen(name, RTLD_GLOBAL | RTLD_LAZY);
871216Sigor@sysoev.ru 
8721983Svbart@nginx.com     if (nxt_slow_path(dl == NULL)) {
8731983Svbart@nginx.com         err = dlerror();
8741983Svbart@nginx.com         nxt_alert(task, "dlopen(\"%s\") failed: \"%s\"",
8751983Svbart@nginx.com                   name, err != NULL ? err : "(null)");
8761983Svbart@nginx.com         return NULL;
877216Sigor@sysoev.ru     }
878216Sigor@sysoev.ru 
8791983Svbart@nginx.com     app = dlsym(dl, "nxt_app_module");
8801983Svbart@nginx.com 
8811983Svbart@nginx.com     if (nxt_slow_path(app == NULL)) {
8821983Svbart@nginx.com         err = dlerror();
8831983Svbart@nginx.com         nxt_alert(task, "dlsym(\"%s\", \"nxt_app_module\") failed: \"%s\"",
8841983Svbart@nginx.com                   name, err != NULL ? err : "(null)");
885216Sigor@sysoev.ru 
8861983Svbart@nginx.com         if (dlclose(dl) != 0) {
8871983Svbart@nginx.com             err = dlerror();
8881983Svbart@nginx.com             nxt_alert(task, "dlclose(\"%s\") failed: \"%s\"",
8891983Svbart@nginx.com                       name, err != NULL ? err : "(null)");
8901983Svbart@nginx.com         }
8911983Svbart@nginx.com     }
8921983Svbart@nginx.com 
8931983Svbart@nginx.com     return app;
894216Sigor@sysoev.ru }
895216Sigor@sysoev.ru 
896216Sigor@sysoev.ru 
897678Svbart@nginx.com static nxt_int_t
nxt_app_set_environment(nxt_conf_value_t * environment)898678Svbart@nginx.com nxt_app_set_environment(nxt_conf_value_t *environment)
899678Svbart@nginx.com {
900678Svbart@nginx.com     char              *env, *p;
901678Svbart@nginx.com     uint32_t          next;
902678Svbart@nginx.com     nxt_str_t         name, value;
903678Svbart@nginx.com     nxt_conf_value_t  *value_obj;
904678Svbart@nginx.com 
905678Svbart@nginx.com     if (environment != NULL) {
906678Svbart@nginx.com         next = 0;
907678Svbart@nginx.com 
908678Svbart@nginx.com         for ( ;; ) {
909678Svbart@nginx.com             value_obj = nxt_conf_next_object_member(environment, &name, &next);
910678Svbart@nginx.com             if (value_obj == NULL) {
911678Svbart@nginx.com                 break;
912678Svbart@nginx.com             }
913678Svbart@nginx.com 
914678Svbart@nginx.com             nxt_conf_get_string(value_obj, &value);
915678Svbart@nginx.com 
916678Svbart@nginx.com             env = nxt_malloc(name.length + value.length + 2);
917678Svbart@nginx.com             if (nxt_slow_path(env == NULL)) {
918678Svbart@nginx.com                 return NXT_ERROR;
919678Svbart@nginx.com             }
920678Svbart@nginx.com 
921678Svbart@nginx.com             p = nxt_cpymem(env, name.start, name.length);
922678Svbart@nginx.com             *p++ = '=';
923678Svbart@nginx.com             p = nxt_cpymem(p, value.start, value.length);
924678Svbart@nginx.com             *p = '\0';
925678Svbart@nginx.com 
926678Svbart@nginx.com             if (nxt_slow_path(putenv(env) != 0)) {
927678Svbart@nginx.com                 return NXT_ERROR;
928678Svbart@nginx.com             }
929678Svbart@nginx.com         }
930678Svbart@nginx.com     }
931678Svbart@nginx.com 
932678Svbart@nginx.com     return NXT_OK;
933678Svbart@nginx.com }
934678Svbart@nginx.com 
935678Svbart@nginx.com 
9362426Sa.clayton@nginx.com nxt_int_t
nxt_app_set_logs(void)9372426Sa.clayton@nginx.com nxt_app_set_logs(void)
9382426Sa.clayton@nginx.com {
9392426Sa.clayton@nginx.com     nxt_int_t              ret;
9402426Sa.clayton@nginx.com     nxt_file_t             file;
9412426Sa.clayton@nginx.com     nxt_task_t             *task;
9422426Sa.clayton@nginx.com     nxt_thread_t           *thr;
9432426Sa.clayton@nginx.com     nxt_process_t          *process;
9442426Sa.clayton@nginx.com     nxt_runtime_t          *rt;
9452426Sa.clayton@nginx.com     nxt_common_app_conf_t  *app_conf;
9462426Sa.clayton@nginx.com 
9472426Sa.clayton@nginx.com     thr = nxt_thread();
9482426Sa.clayton@nginx.com 
9492426Sa.clayton@nginx.com     task = thr->task;
9502426Sa.clayton@nginx.com 
9512426Sa.clayton@nginx.com     rt = task->thread->runtime;
9522426Sa.clayton@nginx.com     if (!rt->daemon) {
9532426Sa.clayton@nginx.com         return NXT_OK;
9542426Sa.clayton@nginx.com     }
9552426Sa.clayton@nginx.com 
9562426Sa.clayton@nginx.com     process = rt->port_by_type[NXT_PROCESS_PROTOTYPE]->process;
9572426Sa.clayton@nginx.com     app_conf = process->data.app;
9582426Sa.clayton@nginx.com 
9592426Sa.clayton@nginx.com     if (app_conf->stdout_log != NULL) {
9602426Sa.clayton@nginx.com         nxt_memzero(&file, sizeof(nxt_file_t));
9612426Sa.clayton@nginx.com         file.log_level = 1;
9622426Sa.clayton@nginx.com         file.name = (u_char *) app_conf->stdout_log;
9632426Sa.clayton@nginx.com         ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, 0666);
9642426Sa.clayton@nginx.com         if (ret == NXT_ERROR) {
9652426Sa.clayton@nginx.com             return NXT_ERROR;
9662426Sa.clayton@nginx.com         }
9672426Sa.clayton@nginx.com 
9682426Sa.clayton@nginx.com         nxt_file_stdout(&file);
9692426Sa.clayton@nginx.com         nxt_file_close(task, &file);
9702426Sa.clayton@nginx.com     }
9712426Sa.clayton@nginx.com 
9722426Sa.clayton@nginx.com     if (app_conf->stderr_log != NULL) {
9732426Sa.clayton@nginx.com         nxt_memzero(&file, sizeof(nxt_file_t));
9742426Sa.clayton@nginx.com         file.log_level = 1;
9752426Sa.clayton@nginx.com         file.name = (u_char *) app_conf->stderr_log;
9762426Sa.clayton@nginx.com         ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT, 0666);
9772426Sa.clayton@nginx.com         if (ret == NXT_ERROR) {
9782426Sa.clayton@nginx.com             return NXT_ERROR;
9792426Sa.clayton@nginx.com         }
9802426Sa.clayton@nginx.com 
9812426Sa.clayton@nginx.com         nxt_file_stderr(&file);
9822426Sa.clayton@nginx.com         nxt_file_close(task, &file);
9832426Sa.clayton@nginx.com     }
9842426Sa.clayton@nginx.com 
9852426Sa.clayton@nginx.com     return NXT_OK;
9862426Sa.clayton@nginx.com }
9872426Sa.clayton@nginx.com 
9882426Sa.clayton@nginx.com 
9891489St.nateldemoura@f5.com static u_char *
nxt_cstr_dup(nxt_mp_t * mp,u_char * dst,u_char * src)9901489St.nateldemoura@f5.com nxt_cstr_dup(nxt_mp_t *mp, u_char *dst, u_char *src)
9911489St.nateldemoura@f5.com {
9921489St.nateldemoura@f5.com     u_char  *p;
9931489St.nateldemoura@f5.com     size_t  len;
9941489St.nateldemoura@f5.com 
9951489St.nateldemoura@f5.com     len = nxt_strlen(src);
9961489St.nateldemoura@f5.com 
9971489St.nateldemoura@f5.com     if (dst == NULL) {
9981489St.nateldemoura@f5.com         dst = nxt_mp_alloc(mp, len + 1);
9991489St.nateldemoura@f5.com         if (nxt_slow_path(dst == NULL)) {
10001489St.nateldemoura@f5.com             return NULL;
10011489St.nateldemoura@f5.com         }
10021489St.nateldemoura@f5.com     }
10031489St.nateldemoura@f5.com 
10041489St.nateldemoura@f5.com     p = nxt_cpymem(dst, src, len);
10051489St.nateldemoura@f5.com     *p = '\0';
10061489St.nateldemoura@f5.com 
10071489St.nateldemoura@f5.com     return dst;
10081489St.nateldemoura@f5.com }
10091489St.nateldemoura@f5.com 
10101488St.nateldemoura@f5.com 
10111998St.nateldemoura@f5.com static nxt_int_t
nxt_app_setup(nxt_task_t * task,nxt_process_t * process)10121998St.nateldemoura@f5.com nxt_app_setup(nxt_task_t *task, nxt_process_t *process)
10131998St.nateldemoura@f5.com {
10141998St.nateldemoura@f5.com     nxt_process_init_t  *init;
10151998St.nateldemoura@f5.com 
10161998St.nateldemoura@f5.com     process->state = NXT_PROCESS_STATE_CREATED;
10171998St.nateldemoura@f5.com 
10181998St.nateldemoura@f5.com     init = nxt_process_init(process);
10191998St.nateldemoura@f5.com 
10201998St.nateldemoura@f5.com     return init->start(task, &process->data);
10211998St.nateldemoura@f5.com }
10221998St.nateldemoura@f5.com 
10231998St.nateldemoura@f5.com 
1024216Sigor@sysoev.ru nxt_app_lang_module_t *
nxt_app_lang_module(nxt_runtime_t * rt,nxt_str_t * name)1025216Sigor@sysoev.ru nxt_app_lang_module(nxt_runtime_t *rt, nxt_str_t *name)
1026216Sigor@sysoev.ru {
1027216Sigor@sysoev.ru     u_char                 *p, *end, *version;
1028356Svbart@nginx.com     size_t                 version_length;
1029216Sigor@sysoev.ru     nxt_uint_t             i, n;
1030356Svbart@nginx.com     nxt_app_type_t         type;
1031216Sigor@sysoev.ru     nxt_app_lang_module_t  *lang;
1032216Sigor@sysoev.ru 
1033216Sigor@sysoev.ru     end = name->start + name->length;
1034216Sigor@sysoev.ru     version = end;
1035216Sigor@sysoev.ru 
1036216Sigor@sysoev.ru     for (p = name->start; p < end; p++) {
1037216Sigor@sysoev.ru         if (*p == ' ') {
1038216Sigor@sysoev.ru             version = p + 1;
1039216Sigor@sysoev.ru             break;
1040216Sigor@sysoev.ru         }
1041216Sigor@sysoev.ru 
1042216Sigor@sysoev.ru         if (*p >= '0' && *p <= '9') {
1043216Sigor@sysoev.ru             version = p;
1044216Sigor@sysoev.ru             break;
1045216Sigor@sysoev.ru         }
1046216Sigor@sysoev.ru     }
1047216Sigor@sysoev.ru 
1048356Svbart@nginx.com     type = nxt_app_parse_type(name->start, p - name->start);
1049356Svbart@nginx.com 
1050356Svbart@nginx.com     if (type == NXT_APP_UNKNOWN) {
1051356Svbart@nginx.com         return NULL;
1052356Svbart@nginx.com     }
1053356Svbart@nginx.com 
1054216Sigor@sysoev.ru     version_length = end - version;
1055216Sigor@sysoev.ru 
1056216Sigor@sysoev.ru     lang = rt->languages->elts;
1057216Sigor@sysoev.ru     n = rt->languages->nelts;
1058216Sigor@sysoev.ru 
1059216Sigor@sysoev.ru     for (i = 0; i < n; i++) {
1060354Svbart@nginx.com 
1061354Svbart@nginx.com         /*
1062354Svbart@nginx.com          * Versions are sorted in descending order
1063354Svbart@nginx.com          * so first match chooses the highest version.
1064354Svbart@nginx.com          */
1065354Svbart@nginx.com 
1066356Svbart@nginx.com         if (lang[i].type == type
1067354Svbart@nginx.com             && nxt_strvers_match(lang[i].version, version, version_length))
1068216Sigor@sysoev.ru         {
1069216Sigor@sysoev.ru             return &lang[i];
1070216Sigor@sysoev.ru         }
1071216Sigor@sysoev.ru     }
1072216Sigor@sysoev.ru 
1073216Sigor@sysoev.ru     return NULL;
1074216Sigor@sysoev.ru }
1075216Sigor@sysoev.ru 
1076216Sigor@sysoev.ru 
1077510Salexander.borisov@nginx.com nxt_app_type_t
nxt_app_parse_type(u_char * p,size_t length)1078356Svbart@nginx.com nxt_app_parse_type(u_char *p, size_t length)
1079141Smax.romanov@nginx.com {
1080356Svbart@nginx.com     nxt_str_t str;
1081356Svbart@nginx.com 
1082356Svbart@nginx.com     str.length = length;
1083356Svbart@nginx.com     str.start = p;
1084356Svbart@nginx.com 
1085804Svbart@nginx.com     if (nxt_str_eq(&str, "external", 8) || nxt_str_eq(&str, "go", 2)) {
1086804Svbart@nginx.com         return NXT_APP_EXTERNAL;
1087804Svbart@nginx.com 
1088804Svbart@nginx.com     } else if (nxt_str_eq(&str, "python", 6)) {
1089141Smax.romanov@nginx.com         return NXT_APP_PYTHON;
1090141Smax.romanov@nginx.com 
1091356Svbart@nginx.com     } else if (nxt_str_eq(&str, "php", 3)) {
1092141Smax.romanov@nginx.com         return NXT_APP_PHP;
1093141Smax.romanov@nginx.com 
1094510Salexander.borisov@nginx.com     } else if (nxt_str_eq(&str, "perl", 4)) {
1095510Salexander.borisov@nginx.com         return NXT_APP_PERL;
1096584Salexander.borisov@nginx.com 
1097584Salexander.borisov@nginx.com     } else if (nxt_str_eq(&str, "ruby", 4)) {
1098584Salexander.borisov@nginx.com         return NXT_APP_RUBY;
1099977Smax.romanov@gmail.com 
1100977Smax.romanov@gmail.com     } else if (nxt_str_eq(&str, "java", 4)) {
1101977Smax.romanov@gmail.com         return NXT_APP_JAVA;
11022518Sa.clayton@nginx.com 
1103*2686Sa.clayton@nginx.com     } else if (nxt_str_eq(&str, "wasm-wasi-component", 19)) {
1104*2686Sa.clayton@nginx.com         return NXT_APP_WASM_WC;
1105*2686Sa.clayton@nginx.com 
11062518Sa.clayton@nginx.com     } else if (nxt_str_eq(&str, "wasm", 4)) {
11072518Sa.clayton@nginx.com         return NXT_APP_WASM;
1108141Smax.romanov@nginx.com     }
1109141Smax.romanov@nginx.com 
1110141Smax.romanov@nginx.com     return NXT_APP_UNKNOWN;
1111141Smax.romanov@nginx.com }
1112743Smax.romanov@nginx.com 
1113743Smax.romanov@nginx.com 
1114743Smax.romanov@nginx.com nxt_int_t
nxt_unit_default_init(nxt_task_t * task,nxt_unit_init_t * init,nxt_common_app_conf_t * conf)11151980Smax.romanov@nginx.com nxt_unit_default_init(nxt_task_t *task, nxt_unit_init_t *init,
11161980Smax.romanov@nginx.com     nxt_common_app_conf_t *conf)
1117743Smax.romanov@nginx.com {
11181998St.nateldemoura@f5.com     nxt_port_t     *my_port, *proto_port, *router_port;
1119743Smax.romanov@nginx.com     nxt_runtime_t  *rt;
1120743Smax.romanov@nginx.com 
1121743Smax.romanov@nginx.com     nxt_memzero(init, sizeof(nxt_unit_init_t));
1122743Smax.romanov@nginx.com 
1123743Smax.romanov@nginx.com     rt = task->thread->runtime;
1124743Smax.romanov@nginx.com 
11251998St.nateldemoura@f5.com     proto_port = rt->port_by_type[NXT_PROCESS_PROTOTYPE];
11261998St.nateldemoura@f5.com     if (nxt_slow_path(proto_port == NULL)) {
1127743Smax.romanov@nginx.com         return NXT_ERROR;
1128743Smax.romanov@nginx.com     }
1129743Smax.romanov@nginx.com 
11301543Smax.romanov@nginx.com     router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
11311543Smax.romanov@nginx.com     if (nxt_slow_path(router_port == NULL)) {
11321543Smax.romanov@nginx.com         return NXT_ERROR;
11331543Smax.romanov@nginx.com     }
11341543Smax.romanov@nginx.com 
1135743Smax.romanov@nginx.com     my_port = nxt_runtime_port_find(rt, nxt_pid, 0);
1136743Smax.romanov@nginx.com     if (nxt_slow_path(my_port == NULL)) {
1137743Smax.romanov@nginx.com         return NXT_ERROR;
1138743Smax.romanov@nginx.com     }
1139743Smax.romanov@nginx.com 
11401998St.nateldemoura@f5.com     init->ready_port.id.pid = proto_port->pid;
11411998St.nateldemoura@f5.com     init->ready_port.id.id = proto_port->id;
11421518Smax.romanov@nginx.com     init->ready_port.in_fd = -1;
11431998St.nateldemoura@f5.com     init->ready_port.out_fd = proto_port->pair[1];
1144743Smax.romanov@nginx.com 
11451488St.nateldemoura@f5.com     init->ready_stream = my_port->process->stream;
1146743Smax.romanov@nginx.com 
11471543Smax.romanov@nginx.com     init->router_port.id.pid = router_port->pid;
11481543Smax.romanov@nginx.com     init->router_port.id.id = router_port->id;
11491543Smax.romanov@nginx.com     init->router_port.in_fd = -1;
11501543Smax.romanov@nginx.com     init->router_port.out_fd = router_port->pair[1];
11511543Smax.romanov@nginx.com 
1152743Smax.romanov@nginx.com     init->read_port.id.pid = my_port->pid;
1153743Smax.romanov@nginx.com     init->read_port.id.id = my_port->id;
1154743Smax.romanov@nginx.com     init->read_port.in_fd = my_port->pair[0];
11551668Smax.romanov@nginx.com     init->read_port.out_fd = my_port->pair[1];
1156743Smax.romanov@nginx.com 
11572014Smax.romanov@nginx.com     init->shared_port_fd = conf->shared_port_fd;
11582014Smax.romanov@nginx.com     init->shared_queue_fd = conf->shared_queue_fd;
11592014Smax.romanov@nginx.com 
1160743Smax.romanov@nginx.com     init->log_fd = 2;
1161743Smax.romanov@nginx.com 
11621980Smax.romanov@nginx.com     init->shm_limit = conf->shm_limit;
11631980Smax.romanov@nginx.com     init->request_limit = conf->request_limit;
11641980Smax.romanov@nginx.com 
1165743Smax.romanov@nginx.com     return NXT_OK;
1166743Smax.romanov@nginx.com }
11671998St.nateldemoura@f5.com 
11681998St.nateldemoura@f5.com 
11691998St.nateldemoura@f5.com static nxt_int_t
nxt_proto_lvlhsh_isolated_pid_test(nxt_lvlhsh_query_t * lhq,void * data)11701998St.nateldemoura@f5.com nxt_proto_lvlhsh_isolated_pid_test(nxt_lvlhsh_query_t *lhq, void *data)
11711998St.nateldemoura@f5.com {
11721998St.nateldemoura@f5.com     nxt_pid_t      *qpid;
11731998St.nateldemoura@f5.com     nxt_process_t  *process;
11741998St.nateldemoura@f5.com 
11751998St.nateldemoura@f5.com     process = data;
11761998St.nateldemoura@f5.com     qpid = (nxt_pid_t *) lhq->key.start;
11771998St.nateldemoura@f5.com 
11781998St.nateldemoura@f5.com     if (*qpid == process->isolated_pid) {
11791998St.nateldemoura@f5.com         return NXT_OK;
11801998St.nateldemoura@f5.com     }
11811998St.nateldemoura@f5.com 
11821998St.nateldemoura@f5.com     return NXT_DECLINED;
11831998St.nateldemoura@f5.com }
11841998St.nateldemoura@f5.com 
11851998St.nateldemoura@f5.com 
11861998St.nateldemoura@f5.com static const nxt_lvlhsh_proto_t  lvlhsh_processes_proto  nxt_aligned(64) = {
11871998St.nateldemoura@f5.com     NXT_LVLHSH_DEFAULT,
11881998St.nateldemoura@f5.com     nxt_proto_lvlhsh_isolated_pid_test,
11891998St.nateldemoura@f5.com     nxt_lvlhsh_alloc,
11901998St.nateldemoura@f5.com     nxt_lvlhsh_free,
11911998St.nateldemoura@f5.com };
11921998St.nateldemoura@f5.com 
11931998St.nateldemoura@f5.com 
11941998St.nateldemoura@f5.com nxt_inline void
nxt_proto_process_lhq_pid(nxt_lvlhsh_query_t * lhq,nxt_pid_t * pid)11951998St.nateldemoura@f5.com nxt_proto_process_lhq_pid(nxt_lvlhsh_query_t *lhq, nxt_pid_t *pid)
11961998St.nateldemoura@f5.com {
11971998St.nateldemoura@f5.com     lhq->key_hash = nxt_murmur_hash2(pid, sizeof(nxt_pid_t));
11981998St.nateldemoura@f5.com     lhq->key.length = sizeof(nxt_pid_t);
11991998St.nateldemoura@f5.com     lhq->key.start = (u_char *) pid;
12001998St.nateldemoura@f5.com     lhq->proto = &lvlhsh_processes_proto;
12011998St.nateldemoura@f5.com }
12021998St.nateldemoura@f5.com 
12031998St.nateldemoura@f5.com 
12041998St.nateldemoura@f5.com static void
nxt_proto_process_add(nxt_task_t * task,nxt_process_t * process)12051998St.nateldemoura@f5.com nxt_proto_process_add(nxt_task_t *task, nxt_process_t *process)
12061998St.nateldemoura@f5.com {
12071998St.nateldemoura@f5.com     nxt_runtime_t       *rt;
12081998St.nateldemoura@f5.com     nxt_lvlhsh_query_t  lhq;
12091998St.nateldemoura@f5.com 
12101998St.nateldemoura@f5.com     rt = task->thread->runtime;
12111998St.nateldemoura@f5.com 
12121998St.nateldemoura@f5.com     nxt_proto_process_lhq_pid(&lhq, &process->isolated_pid);
12131998St.nateldemoura@f5.com 
12141998St.nateldemoura@f5.com     lhq.replace = 0;
12151998St.nateldemoura@f5.com     lhq.value = process;
12161998St.nateldemoura@f5.com     lhq.pool = rt->mem_pool;
12171998St.nateldemoura@f5.com 
12181998St.nateldemoura@f5.com     switch (nxt_lvlhsh_insert(&nxt_proto_processes, &lhq)) {
12191998St.nateldemoura@f5.com 
12201998St.nateldemoura@f5.com     case NXT_OK:
12211998St.nateldemoura@f5.com         nxt_debug(task, "process (isolated %PI) added", process->isolated_pid);
12221998St.nateldemoura@f5.com 
12231998St.nateldemoura@f5.com         nxt_queue_insert_tail(&nxt_proto_children, &process->link);
12241998St.nateldemoura@f5.com         break;
12251998St.nateldemoura@f5.com 
12261998St.nateldemoura@f5.com     default:
12272174Smax.romanov@gmail.com         nxt_alert(task, "process (isolated %PI) failed to add",
12281998St.nateldemoura@f5.com                   process->isolated_pid);
12291998St.nateldemoura@f5.com         break;
12301998St.nateldemoura@f5.com     }
12311998St.nateldemoura@f5.com }
12321998St.nateldemoura@f5.com 
12331998St.nateldemoura@f5.com 
12341998St.nateldemoura@f5.com static nxt_process_t *
nxt_proto_process_remove(nxt_task_t * task,nxt_pid_t pid)12351998St.nateldemoura@f5.com nxt_proto_process_remove(nxt_task_t *task, nxt_pid_t pid)
12361998St.nateldemoura@f5.com {
12371998St.nateldemoura@f5.com     nxt_runtime_t       *rt;
12381998St.nateldemoura@f5.com     nxt_process_t       *process;
12391998St.nateldemoura@f5.com     nxt_lvlhsh_query_t  lhq;
12401998St.nateldemoura@f5.com 
12411998St.nateldemoura@f5.com     nxt_proto_process_lhq_pid(&lhq, &pid);
12421998St.nateldemoura@f5.com 
12431998St.nateldemoura@f5.com     rt = task->thread->runtime;
12441998St.nateldemoura@f5.com 
12451998St.nateldemoura@f5.com     lhq.pool = rt->mem_pool;
12461998St.nateldemoura@f5.com 
12471998St.nateldemoura@f5.com     switch (nxt_lvlhsh_delete(&nxt_proto_processes, &lhq)) {
12481998St.nateldemoura@f5.com 
12491998St.nateldemoura@f5.com     case NXT_OK:
12501998St.nateldemoura@f5.com         nxt_debug(task, "process (isolated %PI) removed", pid);
12511998St.nateldemoura@f5.com 
12521998St.nateldemoura@f5.com         process = lhq.value;
12531998St.nateldemoura@f5.com 
12541998St.nateldemoura@f5.com         nxt_queue_remove(&process->link);
12552040Smax.romanov@nginx.com         process->link.next = NULL;
12562040Smax.romanov@nginx.com 
12571998St.nateldemoura@f5.com         break;
12581998St.nateldemoura@f5.com 
12591998St.nateldemoura@f5.com     default:
12601998St.nateldemoura@f5.com         nxt_debug(task, "process (isolated %PI) remove failed", pid);
12611998St.nateldemoura@f5.com         process = NULL;
12621998St.nateldemoura@f5.com         break;
12631998St.nateldemoura@f5.com     }
12641998St.nateldemoura@f5.com 
12651998St.nateldemoura@f5.com     return process;
12661998St.nateldemoura@f5.com }
12671998St.nateldemoura@f5.com 
12681998St.nateldemoura@f5.com 
12691998St.nateldemoura@f5.com static nxt_process_t *
nxt_proto_process_find(nxt_task_t * task,nxt_pid_t pid)12701998St.nateldemoura@f5.com nxt_proto_process_find(nxt_task_t *task, nxt_pid_t pid)
12711998St.nateldemoura@f5.com {
12721998St.nateldemoura@f5.com     nxt_process_t       *process;
12731998St.nateldemoura@f5.com     nxt_lvlhsh_query_t  lhq;
12741998St.nateldemoura@f5.com 
12751998St.nateldemoura@f5.com     nxt_proto_process_lhq_pid(&lhq, &pid);
12761998St.nateldemoura@f5.com 
12771998St.nateldemoura@f5.com     if (nxt_lvlhsh_find(&nxt_proto_processes, &lhq) == NXT_OK) {
12781998St.nateldemoura@f5.com         process = lhq.value;
12791998St.nateldemoura@f5.com 
12801998St.nateldemoura@f5.com     } else {
12811998St.nateldemoura@f5.com         nxt_debug(task, "process (isolated %PI) not found", pid);
12821998St.nateldemoura@f5.com 
12831998St.nateldemoura@f5.com         process = NULL;
12841998St.nateldemoura@f5.com     }
12851998St.nateldemoura@f5.com 
12861998St.nateldemoura@f5.com     return process;
12871998St.nateldemoura@f5.com }
1288