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