xref: /unit/src/nxt_main_process.c (revision 1996)
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 
34240Sigor@sysoev.ru static nxt_int_t nxt_main_process_port_create(nxt_task_t *task,
35240Sigor@sysoev.ru     nxt_runtime_t *rt);
36240Sigor@sysoev.ru static void nxt_main_process_title(nxt_task_t *task);
371488St.nateldemoura@f5.com static nxt_int_t nxt_main_process_create(nxt_task_t *task,
381488St.nateldemoura@f5.com     const nxt_process_init_t init);
391488St.nateldemoura@f5.com static nxt_int_t nxt_main_start_process(nxt_task_t *task,
401488St.nateldemoura@f5.com     nxt_process_t *process);
411488St.nateldemoura@f5.com static nxt_process_t *nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt);
42240Sigor@sysoev.ru static void nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj,
43240Sigor@sysoev.ru     void *data);
44240Sigor@sysoev.ru static void nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj,
45240Sigor@sysoev.ru     void *data);
46240Sigor@sysoev.ru static void nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj,
47240Sigor@sysoev.ru     void *data);
48240Sigor@sysoev.ru static void nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj,
49240Sigor@sysoev.ru     void *data);
50944Sigor@sysoev.ru static void nxt_main_process_signal_handler(nxt_task_t *task, void *obj,
51944Sigor@sysoev.ru     void *data);
521488St.nateldemoura@f5.com static void nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid);
53240Sigor@sysoev.ru static void nxt_main_port_socket_handler(nxt_task_t *task,
54240Sigor@sysoev.ru     nxt_port_recv_msg_t *msg);
55240Sigor@sysoev.ru static nxt_int_t nxt_main_listening_socket(nxt_sockaddr_t *sa,
56240Sigor@sysoev.ru     nxt_listening_socket_t *ls);
57240Sigor@sysoev.ru static void nxt_main_port_modules_handler(nxt_task_t *task,
58240Sigor@sysoev.ru     nxt_port_recv_msg_t *msg);
59240Sigor@sysoev.ru static int nxt_cdecl nxt_app_lang_compare(const void *v1, const void *v2);
60314Svbart@nginx.com static void nxt_main_port_conf_store_handler(nxt_task_t *task,
61314Svbart@nginx.com     nxt_port_recv_msg_t *msg);
621969Sz.hong@f5.com static nxt_int_t nxt_main_file_store(nxt_task_t *task, const char *tmp_name,
631969Sz.hong@f5.com     const char *name, u_char *buf, size_t size);
64630Svbart@nginx.com static void nxt_main_port_access_log_handler(nxt_task_t *task,
65630Svbart@nginx.com     nxt_port_recv_msg_t *msg);
66240Sigor@sysoev.ru 
67240Sigor@sysoev.ru const nxt_sig_event_t  nxt_main_process_signals[] = {
68944Sigor@sysoev.ru     nxt_event_signal(SIGHUP,  nxt_main_process_signal_handler),
69240Sigor@sysoev.ru     nxt_event_signal(SIGINT,  nxt_main_process_sigterm_handler),
70240Sigor@sysoev.ru     nxt_event_signal(SIGQUIT, nxt_main_process_sigquit_handler),
71240Sigor@sysoev.ru     nxt_event_signal(SIGTERM, nxt_main_process_sigterm_handler),
72240Sigor@sysoev.ru     nxt_event_signal(SIGCHLD, nxt_main_process_sigchld_handler),
73240Sigor@sysoev.ru     nxt_event_signal(SIGUSR1, nxt_main_process_sigusr1_handler),
74240Sigor@sysoev.ru     nxt_event_signal_end,
75240Sigor@sysoev.ru };
76240Sigor@sysoev.ru 
77240Sigor@sysoev.ru 
781969Sz.hong@f5.com nxt_uint_t  nxt_conf_ver;
791969Sz.hong@f5.com 
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 
1571980Smax.romanov@nginx.com     {
1581980Smax.romanov@nginx.com         nxt_string("requests"),
1591980Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
1601980Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, request_limit),
1611980Smax.romanov@nginx.com     },
1621980Smax.romanov@nginx.com 
163510Salexander.borisov@nginx.com };
164271Smax.romanov@nginx.com 
165510Salexander.borisov@nginx.com 
166804Svbart@nginx.com static nxt_conf_map_t  nxt_external_app_conf[] = {
167804Svbart@nginx.com     {
168804Svbart@nginx.com         nxt_string("executable"),
169804Svbart@nginx.com         NXT_CONF_MAP_CSTRZ,
170804Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.external.executable),
171804Svbart@nginx.com     },
172804Svbart@nginx.com 
173804Svbart@nginx.com     {
174804Svbart@nginx.com         nxt_string("arguments"),
175804Svbart@nginx.com         NXT_CONF_MAP_PTR,
176804Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.external.arguments),
177804Svbart@nginx.com     },
178804Svbart@nginx.com 
179804Svbart@nginx.com };
180804Svbart@nginx.com 
181804Svbart@nginx.com 
182546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_python_app_conf[] = {
183271Smax.romanov@nginx.com     {
184394Smax.romanov@nginx.com         nxt_string("home"),
185394Smax.romanov@nginx.com         NXT_CONF_MAP_CSTRZ,
186394Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.home),
187394Smax.romanov@nginx.com     },
188394Smax.romanov@nginx.com 
189394Smax.romanov@nginx.com     {
190240Sigor@sysoev.ru         nxt_string("path"),
1911759Svbart@nginx.com         NXT_CONF_MAP_PTR,
192240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, u.python.path),
193240Sigor@sysoev.ru     },
194240Sigor@sysoev.ru 
195240Sigor@sysoev.ru     {
196240Sigor@sysoev.ru         nxt_string("module"),
197240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
198240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, u.python.module),
199240Sigor@sysoev.ru     },
2001601Smax.romanov@nginx.com 
2011601Smax.romanov@nginx.com     {
2021601Smax.romanov@nginx.com         nxt_string("callable"),
2031601Smax.romanov@nginx.com         NXT_CONF_MAP_CSTRZ,
2041601Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.callable),
2051601Smax.romanov@nginx.com     },
2061681Smax.romanov@nginx.com 
2071681Smax.romanov@nginx.com     {
2081697Smax.romanov@nginx.com         nxt_string("protocol"),
2091697Smax.romanov@nginx.com         NXT_CONF_MAP_STR,
2101697Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.protocol),
2111697Smax.romanov@nginx.com     },
2121697Smax.romanov@nginx.com 
2131697Smax.romanov@nginx.com     {
2141681Smax.romanov@nginx.com         nxt_string("threads"),
2151681Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2161681Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.threads),
2171681Smax.romanov@nginx.com     },
2181681Smax.romanov@nginx.com 
2191681Smax.romanov@nginx.com     {
2201872So.canty@f5.com         nxt_string("targets"),
2211872So.canty@f5.com         NXT_CONF_MAP_PTR,
2221872So.canty@f5.com         offsetof(nxt_common_app_conf_t, u.python.targets),
2231872So.canty@f5.com     },
2241872So.canty@f5.com 
2251872So.canty@f5.com     {
2261681Smax.romanov@nginx.com         nxt_string("thread_stack_size"),
2271681Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2281681Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.thread_stack_size),
2291681Smax.romanov@nginx.com     },
230510Salexander.borisov@nginx.com };
231240Sigor@sysoev.ru 
232510Salexander.borisov@nginx.com 
233546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_php_app_conf[] = {
234240Sigor@sysoev.ru     {
2351473Svbart@nginx.com         nxt_string("targets"),
2361473Svbart@nginx.com         NXT_CONF_MAP_PTR,
2371473Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.php.targets),
238240Sigor@sysoev.ru     },
239687Svbart@nginx.com 
240687Svbart@nginx.com     {
241687Svbart@nginx.com         nxt_string("options"),
242687Svbart@nginx.com         NXT_CONF_MAP_PTR,
243687Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.php.options),
244687Svbart@nginx.com     },
245510Salexander.borisov@nginx.com };
246240Sigor@sysoev.ru 
247510Salexander.borisov@nginx.com 
248546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_perl_app_conf[] = {
249510Salexander.borisov@nginx.com     {
250510Salexander.borisov@nginx.com         nxt_string("script"),
251510Salexander.borisov@nginx.com         NXT_CONF_MAP_CSTRZ,
252510Salexander.borisov@nginx.com         offsetof(nxt_common_app_conf_t, u.perl.script),
253510Salexander.borisov@nginx.com     },
2541689Smax.romanov@nginx.com 
2551689Smax.romanov@nginx.com     {
2561689Smax.romanov@nginx.com         nxt_string("threads"),
2571689Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2581689Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.perl.threads),
2591689Smax.romanov@nginx.com     },
2601689Smax.romanov@nginx.com 
2611689Smax.romanov@nginx.com     {
2621689Smax.romanov@nginx.com         nxt_string("thread_stack_size"),
2631689Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2641689Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.perl.thread_stack_size),
2651689Smax.romanov@nginx.com     },
266510Salexander.borisov@nginx.com };
267510Salexander.borisov@nginx.com 
268510Salexander.borisov@nginx.com 
269584Salexander.borisov@nginx.com static nxt_conf_map_t  nxt_ruby_app_conf[] = {
270584Salexander.borisov@nginx.com     {
271584Salexander.borisov@nginx.com         nxt_string("script"),
272584Salexander.borisov@nginx.com         NXT_CONF_MAP_STR,
273584Salexander.borisov@nginx.com         offsetof(nxt_common_app_conf_t, u.ruby.script),
274584Salexander.borisov@nginx.com     },
2751687Smax.romanov@nginx.com     {
2761687Smax.romanov@nginx.com         nxt_string("threads"),
2771687Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2781687Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.ruby.threads),
2791687Smax.romanov@nginx.com     },
2801910So.canty@f5.com     {
2811910So.canty@f5.com         nxt_string("hooks"),
2821910So.canty@f5.com         NXT_CONF_MAP_STR,
2831910So.canty@f5.com         offsetof(nxt_common_app_conf_t, u.ruby.hooks),
2841910So.canty@f5.com     }
285584Salexander.borisov@nginx.com };
286584Salexander.borisov@nginx.com 
287584Salexander.borisov@nginx.com 
288977Smax.romanov@gmail.com static nxt_conf_map_t  nxt_java_app_conf[] = {
289977Smax.romanov@gmail.com     {
290977Smax.romanov@gmail.com         nxt_string("classpath"),
291977Smax.romanov@gmail.com         NXT_CONF_MAP_PTR,
292977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.classpath),
293977Smax.romanov@gmail.com     },
294977Smax.romanov@gmail.com     {
295977Smax.romanov@gmail.com         nxt_string("webapp"),
296977Smax.romanov@gmail.com         NXT_CONF_MAP_CSTRZ,
297977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.webapp),
298977Smax.romanov@gmail.com     },
299977Smax.romanov@gmail.com     {
300977Smax.romanov@gmail.com         nxt_string("options"),
301977Smax.romanov@gmail.com         NXT_CONF_MAP_PTR,
302977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.options),
303977Smax.romanov@gmail.com     },
304977Smax.romanov@gmail.com     {
305977Smax.romanov@gmail.com         nxt_string("unit_jars"),
306977Smax.romanov@gmail.com         NXT_CONF_MAP_CSTRZ,
307977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.unit_jars),
308977Smax.romanov@gmail.com     },
3091684Smax.romanov@nginx.com     {
3101684Smax.romanov@nginx.com         nxt_string("threads"),
3111684Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
3121684Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.java.threads),
3131684Smax.romanov@nginx.com     },
3141684Smax.romanov@nginx.com     {
3151684Smax.romanov@nginx.com         nxt_string("thread_stack_size"),
3161684Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
3171684Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.java.thread_stack_size),
3181684Smax.romanov@nginx.com     },
319977Smax.romanov@gmail.com 
320977Smax.romanov@gmail.com };
321977Smax.romanov@gmail.com 
322977Smax.romanov@gmail.com 
323546Smax.romanov@nginx.com static nxt_conf_app_map_t  nxt_app_maps[] = {
324804Svbart@nginx.com     { nxt_nitems(nxt_external_app_conf),  nxt_external_app_conf },
325804Svbart@nginx.com     { nxt_nitems(nxt_python_app_conf),    nxt_python_app_conf },
326804Svbart@nginx.com     { nxt_nitems(nxt_php_app_conf),       nxt_php_app_conf },
327804Svbart@nginx.com     { nxt_nitems(nxt_perl_app_conf),      nxt_perl_app_conf },
328804Svbart@nginx.com     { nxt_nitems(nxt_ruby_app_conf),      nxt_ruby_app_conf },
329977Smax.romanov@gmail.com     { nxt_nitems(nxt_java_app_conf),      nxt_java_app_conf },
330510Salexander.borisov@nginx.com };
331510Salexander.borisov@nginx.com 
332510Salexander.borisov@nginx.com 
333240Sigor@sysoev.ru static void
334240Sigor@sysoev.ru nxt_port_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
335240Sigor@sysoev.ru {
336240Sigor@sysoev.ru     nxt_debug(task, "main data: %*s",
337240Sigor@sysoev.ru               nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos);
338240Sigor@sysoev.ru }
339240Sigor@sysoev.ru 
340240Sigor@sysoev.ru 
341240Sigor@sysoev.ru static void
3421488St.nateldemoura@f5.com nxt_port_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
343240Sigor@sysoev.ru {
3441488St.nateldemoura@f5.com     u_char                 *start, *p, ch;
345536Svbart@nginx.com     size_t                 type_len;
346536Svbart@nginx.com     nxt_int_t              ret;
347240Sigor@sysoev.ru     nxt_buf_t              *b;
348318Smax.romanov@nginx.com     nxt_port_t             *port;
3491182St.nateldemoura@f5.com     nxt_runtime_t          *rt;
3501488St.nateldemoura@f5.com     nxt_process_t          *process;
351536Svbart@nginx.com     nxt_app_type_t         idx;
352240Sigor@sysoev.ru     nxt_conf_value_t       *conf;
3531488St.nateldemoura@f5.com     nxt_process_init_t     *init;
3541488St.nateldemoura@f5.com     nxt_common_app_conf_t  *app_conf;
355240Sigor@sysoev.ru 
3561488St.nateldemoura@f5.com     rt = task->thread->runtime;
357352Smax.romanov@nginx.com 
358*1996St.nateldemoura@f5.com     port = rt->port_by_type[NXT_PROCESS_ROUTER];
359*1996St.nateldemoura@f5.com     if (nxt_slow_path(port == NULL)) {
360*1996St.nateldemoura@f5.com         nxt_alert(task, "router port not found");
361*1996St.nateldemoura@f5.com         return;
362*1996St.nateldemoura@f5.com     }
363*1996St.nateldemoura@f5.com 
364*1996St.nateldemoura@f5.com     if (nxt_slow_path(port->pid != nxt_recv_msg_cmsg_pid(msg))) {
365*1996St.nateldemoura@f5.com         nxt_alert(task, "process %PI cannot start processes",
366*1996St.nateldemoura@f5.com                   nxt_recv_msg_cmsg_pid(msg));
367*1996St.nateldemoura@f5.com 
368*1996St.nateldemoura@f5.com         return;
369*1996St.nateldemoura@f5.com     }
370*1996St.nateldemoura@f5.com 
3711488St.nateldemoura@f5.com     process = nxt_main_process_new(task, rt);
3721488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
373352Smax.romanov@nginx.com         return;
374352Smax.romanov@nginx.com     }
375352Smax.romanov@nginx.com 
3761488St.nateldemoura@f5.com     init = nxt_process_init(process);
3771488St.nateldemoura@f5.com 
3781488St.nateldemoura@f5.com     *init = nxt_app_process;
379352Smax.romanov@nginx.com 
3801488St.nateldemoura@f5.com     b = nxt_buf_chk_make_plain(process->mem_pool, msg->buf, msg->size);
381352Smax.romanov@nginx.com     if (b == NULL) {
3821488St.nateldemoura@f5.com         goto failed;
383352Smax.romanov@nginx.com     }
384240Sigor@sysoev.ru 
3851488St.nateldemoura@f5.com     nxt_debug(task, "main start process: %*s", b->mem.free - b->mem.pos,
386240Sigor@sysoev.ru               b->mem.pos);
387240Sigor@sysoev.ru 
3881488St.nateldemoura@f5.com     app_conf = nxt_mp_zalloc(process->mem_pool, sizeof(nxt_common_app_conf_t));
3891488St.nateldemoura@f5.com     if (nxt_slow_path(app_conf == NULL)) {
3901488St.nateldemoura@f5.com         goto failed;
3911488St.nateldemoura@f5.com     }
392240Sigor@sysoev.ru 
393240Sigor@sysoev.ru     start = b->mem.pos;
394240Sigor@sysoev.ru 
3951488St.nateldemoura@f5.com     app_conf->name.start = start;
3961488St.nateldemoura@f5.com     app_conf->name.length = nxt_strlen(start);
3971488St.nateldemoura@f5.com 
3981488St.nateldemoura@f5.com     init->name = (const char *) start;
3991488St.nateldemoura@f5.com 
4001488St.nateldemoura@f5.com     process->name = nxt_mp_alloc(process->mem_pool, app_conf->name.length
4011488St.nateldemoura@f5.com                                  + sizeof("\"\" application") + 1);
4021488St.nateldemoura@f5.com 
4031488St.nateldemoura@f5.com     if (nxt_slow_path(process->name == NULL)) {
4041488St.nateldemoura@f5.com         goto failed;
4051488St.nateldemoura@f5.com     }
406240Sigor@sysoev.ru 
4071488St.nateldemoura@f5.com     p = (u_char *) process->name;
4081488St.nateldemoura@f5.com     *p++ = '"';
4091488St.nateldemoura@f5.com     p = nxt_cpymem(p, init->name, app_conf->name.length);
4101488St.nateldemoura@f5.com     p = nxt_cpymem(p, "\" application", 13);
4111488St.nateldemoura@f5.com     *p = '\0';
412240Sigor@sysoev.ru 
4131488St.nateldemoura@f5.com     app_conf->shm_limit = 100 * 1024 * 1024;
4141980Smax.romanov@nginx.com     app_conf->request_limit = 0;
415240Sigor@sysoev.ru 
4161488St.nateldemoura@f5.com     start += app_conf->name.length + 1;
4171488St.nateldemoura@f5.com 
4181488St.nateldemoura@f5.com     conf = nxt_conf_json_parse(process->mem_pool, start, b->mem.free, NULL);
419240Sigor@sysoev.ru     if (conf == NULL) {
420564Svbart@nginx.com         nxt_alert(task, "router app configuration parsing error");
421318Smax.romanov@nginx.com 
422318Smax.romanov@nginx.com         goto failed;
423240Sigor@sysoev.ru     }
424240Sigor@sysoev.ru 
4251182St.nateldemoura@f5.com     rt = task->thread->runtime;
4261182St.nateldemoura@f5.com 
4271488St.nateldemoura@f5.com     app_conf->user.start  = (u_char*)rt->user_cred.user;
4281488St.nateldemoura@f5.com     app_conf->user.length = nxt_strlen(rt->user_cred.user);
429240Sigor@sysoev.ru 
4301488St.nateldemoura@f5.com     ret = nxt_conf_map_object(process->mem_pool, conf, nxt_common_app_conf,
4311488St.nateldemoura@f5.com                               nxt_nitems(nxt_common_app_conf), app_conf);
4321488St.nateldemoura@f5.com 
433240Sigor@sysoev.ru     if (ret != NXT_OK) {
434564Svbart@nginx.com         nxt_alert(task, "failed to map common app conf received from router");
435318Smax.romanov@nginx.com         goto failed;
436240Sigor@sysoev.ru     }
437240Sigor@sysoev.ru 
4381488St.nateldemoura@f5.com     for (type_len = 0; type_len != app_conf->type.length; type_len++) {
4391488St.nateldemoura@f5.com         ch = app_conf->type.start[type_len];
440536Svbart@nginx.com 
441536Svbart@nginx.com         if (ch == ' ' || nxt_isdigit(ch)) {
442536Svbart@nginx.com             break;
443536Svbart@nginx.com         }
444536Svbart@nginx.com     }
445536Svbart@nginx.com 
4461488St.nateldemoura@f5.com     idx = nxt_app_parse_type(app_conf->type.start, type_len);
447510Salexander.borisov@nginx.com 
448546Smax.romanov@nginx.com     if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) {
449564Svbart@nginx.com         nxt_alert(task, "invalid app type %d received from router", (int) idx);
450546Smax.romanov@nginx.com         goto failed;
451546Smax.romanov@nginx.com     }
452510Salexander.borisov@nginx.com 
4531488St.nateldemoura@f5.com     ret = nxt_conf_map_object(process->mem_pool, conf, nxt_app_maps[idx].map,
4541488St.nateldemoura@f5.com                               nxt_app_maps[idx].size, app_conf);
455510Salexander.borisov@nginx.com 
456546Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
457564Svbart@nginx.com         nxt_alert(task, "failed to map app conf received from router");
458546Smax.romanov@nginx.com         goto failed;
459546Smax.romanov@nginx.com     }
460510Salexander.borisov@nginx.com 
4611488St.nateldemoura@f5.com     if (app_conf->limits != NULL) {
4621488St.nateldemoura@f5.com         ret = nxt_conf_map_object(process->mem_pool, app_conf->limits,
4631320Smax.romanov@nginx.com                                   nxt_common_app_limits_conf,
4641320Smax.romanov@nginx.com                                   nxt_nitems(nxt_common_app_limits_conf),
4651488St.nateldemoura@f5.com                                   app_conf);
4661320Smax.romanov@nginx.com 
4671320Smax.romanov@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
4681320Smax.romanov@nginx.com             nxt_alert(task, "failed to map app limits received from router");
4691320Smax.romanov@nginx.com             goto failed;
4701320Smax.romanov@nginx.com         }
4711320Smax.romanov@nginx.com     }
4721320Smax.romanov@nginx.com 
4731488St.nateldemoura@f5.com     app_conf->self = conf;
4741488St.nateldemoura@f5.com 
4751488St.nateldemoura@f5.com     process->stream = msg->port_msg.stream;
4761488St.nateldemoura@f5.com     process->data.app = app_conf;
4771473Svbart@nginx.com 
4781488St.nateldemoura@f5.com     ret = nxt_main_start_process(task, process);
4791488St.nateldemoura@f5.com     if (nxt_fast_path(ret == NXT_OK || ret == NXT_AGAIN)) {
4801488St.nateldemoura@f5.com         return;
4811488St.nateldemoura@f5.com     }
482240Sigor@sysoev.ru 
483318Smax.romanov@nginx.com failed:
484318Smax.romanov@nginx.com 
4851488St.nateldemoura@f5.com     nxt_process_use(task, process, -1);
4861488St.nateldemoura@f5.com 
4871488St.nateldemoura@f5.com     port = nxt_runtime_port_find(rt, msg->port_msg.pid,
4881488St.nateldemoura@f5.com                                  msg->port_msg.reply_port);
4891488St.nateldemoura@f5.com 
4901488St.nateldemoura@f5.com     if (nxt_fast_path(port != NULL)) {
4911488St.nateldemoura@f5.com         nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
4921488St.nateldemoura@f5.com                               -1, msg->port_msg.stream, 0, NULL);
4931488St.nateldemoura@f5.com     }
4941488St.nateldemoura@f5.com }
4951488St.nateldemoura@f5.com 
4961488St.nateldemoura@f5.com 
4971488St.nateldemoura@f5.com static void
4981488St.nateldemoura@f5.com nxt_main_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
4991488St.nateldemoura@f5.com {
5001488St.nateldemoura@f5.com     nxt_port_t     *port;
5011488St.nateldemoura@f5.com     nxt_process_t  *process;
5021488St.nateldemoura@f5.com     nxt_runtime_t  *rt;
5031488St.nateldemoura@f5.com 
5041488St.nateldemoura@f5.com     rt = task->thread->runtime;
5051488St.nateldemoura@f5.com 
5061488St.nateldemoura@f5.com     process = nxt_runtime_process_find(rt, msg->port_msg.pid);
5071488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
5081488St.nateldemoura@f5.com         return;
509318Smax.romanov@nginx.com     }
510318Smax.romanov@nginx.com 
5111488St.nateldemoura@f5.com     nxt_assert(process->state == NXT_PROCESS_STATE_CREATING);
5121488St.nateldemoura@f5.com 
5131488St.nateldemoura@f5.com     port = nxt_runtime_port_find(rt, msg->port_msg.pid,
5141488St.nateldemoura@f5.com                                  msg->port_msg.reply_port);
5151488St.nateldemoura@f5.com 
5161488St.nateldemoura@f5.com 
5171488St.nateldemoura@f5.com     if (nxt_slow_path(port == NULL)) {
5181488St.nateldemoura@f5.com         return;
5191488St.nateldemoura@f5.com     }
5201488St.nateldemoura@f5.com 
5211488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER)
5221488St.nateldemoura@f5.com     if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
5231488St.nateldemoura@f5.com         if (nxt_slow_path(nxt_clone_credential_map(task, process->pid,
5241488St.nateldemoura@f5.com                                                    process->user_cred,
5251488St.nateldemoura@f5.com                                                    &process->isolation.clone)
5261488St.nateldemoura@f5.com                           != NXT_OK))
5271488St.nateldemoura@f5.com         {
5281488St.nateldemoura@f5.com             (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
5291488St.nateldemoura@f5.com                                          -1, msg->port_msg.stream, 0, NULL);
5301488St.nateldemoura@f5.com             return;
5311488St.nateldemoura@f5.com         }
5321488St.nateldemoura@f5.com      }
5331488St.nateldemoura@f5.com 
5341488St.nateldemoura@f5.com #endif
5351488St.nateldemoura@f5.com 
5361488St.nateldemoura@f5.com     process->state = NXT_PROCESS_STATE_CREATED;
5371488St.nateldemoura@f5.com 
5381488St.nateldemoura@f5.com     (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST,
5391488St.nateldemoura@f5.com                                  -1, msg->port_msg.stream, 0, NULL);
540240Sigor@sysoev.ru }
541240Sigor@sysoev.ru 
542240Sigor@sysoev.ru 
543320Smax.romanov@nginx.com static nxt_port_handlers_t  nxt_main_process_port_handlers = {
5441488St.nateldemoura@f5.com     .data             = nxt_port_main_data_handler,
5451488St.nateldemoura@f5.com     .process_created  = nxt_main_process_created_handler,
5461488St.nateldemoura@f5.com     .process_ready    = nxt_port_process_ready_handler,
5471488St.nateldemoura@f5.com     .start_process    = nxt_port_main_start_process_handler,
5481488St.nateldemoura@f5.com     .socket           = nxt_main_port_socket_handler,
5491488St.nateldemoura@f5.com     .modules          = nxt_main_port_modules_handler,
5501488St.nateldemoura@f5.com     .conf_store       = nxt_main_port_conf_store_handler,
551774Svbart@nginx.com #if (NXT_TLS)
5521488St.nateldemoura@f5.com     .cert_get         = nxt_cert_store_get_handler,
5531488St.nateldemoura@f5.com     .cert_delete      = nxt_cert_store_delete_handler,
554774Svbart@nginx.com #endif
5551488St.nateldemoura@f5.com     .access_log       = nxt_main_port_access_log_handler,
5561488St.nateldemoura@f5.com     .rpc_ready        = nxt_port_rpc_handler,
5571488St.nateldemoura@f5.com     .rpc_error        = nxt_port_rpc_handler,
558240Sigor@sysoev.ru };
559240Sigor@sysoev.ru 
560240Sigor@sysoev.ru 
561240Sigor@sysoev.ru static nxt_int_t
562240Sigor@sysoev.ru nxt_main_process_port_create(nxt_task_t *task, nxt_runtime_t *rt)
563240Sigor@sysoev.ru {
564240Sigor@sysoev.ru     nxt_int_t      ret;
565240Sigor@sysoev.ru     nxt_port_t     *port;
566240Sigor@sysoev.ru     nxt_process_t  *process;
567240Sigor@sysoev.ru 
5681254Shongzhidao@gmail.com     port = nxt_runtime_process_port_create(task, rt, nxt_pid, 0,
5691254Shongzhidao@gmail.com                                            NXT_PROCESS_MAIN);
570240Sigor@sysoev.ru     if (nxt_slow_path(port == NULL)) {
571240Sigor@sysoev.ru         return NXT_ERROR;
572240Sigor@sysoev.ru     }
573240Sigor@sysoev.ru 
5741254Shongzhidao@gmail.com     process = port->process;
575349Smax.romanov@nginx.com 
576240Sigor@sysoev.ru     ret = nxt_port_socket_init(task, port, 0);
577240Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
5781488St.nateldemoura@f5.com         nxt_port_use(task, port, -1);
579240Sigor@sysoev.ru         return ret;
580240Sigor@sysoev.ru     }
581240Sigor@sysoev.ru 
582240Sigor@sysoev.ru     /*
583240Sigor@sysoev.ru      * A main process port.  A write port is not closed
5841488St.nateldemoura@f5.com      * since it should be inherited by processes.
585240Sigor@sysoev.ru      */
586320Smax.romanov@nginx.com     nxt_port_enable(task, port, &nxt_main_process_port_handlers);
587240Sigor@sysoev.ru 
5881488St.nateldemoura@f5.com     process->state = NXT_PROCESS_STATE_READY;
589240Sigor@sysoev.ru 
590240Sigor@sysoev.ru     return NXT_OK;
591240Sigor@sysoev.ru }
592240Sigor@sysoev.ru 
593240Sigor@sysoev.ru 
594240Sigor@sysoev.ru static void
595240Sigor@sysoev.ru nxt_main_process_title(nxt_task_t *task)
596240Sigor@sysoev.ru {
597240Sigor@sysoev.ru     u_char      *p, *end;
598240Sigor@sysoev.ru     nxt_uint_t  i;
599240Sigor@sysoev.ru     u_char      title[2048];
600240Sigor@sysoev.ru 
601240Sigor@sysoev.ru     end = title + sizeof(title) - 1;
602240Sigor@sysoev.ru 
603680Sigor@sysoev.ru     p = nxt_sprintf(title, end, "unit: main v" NXT_VERSION " [%s",
604680Sigor@sysoev.ru                     nxt_process_argv[0]);
605240Sigor@sysoev.ru 
606240Sigor@sysoev.ru     for (i = 1; nxt_process_argv[i] != NULL; i++) {
607240Sigor@sysoev.ru         p = nxt_sprintf(p, end, " %s", nxt_process_argv[i]);
608240Sigor@sysoev.ru     }
609240Sigor@sysoev.ru 
610240Sigor@sysoev.ru     if (p < end) {
611240Sigor@sysoev.ru         *p++ = ']';
612240Sigor@sysoev.ru     }
613240Sigor@sysoev.ru 
614240Sigor@sysoev.ru     *p = '\0';
615240Sigor@sysoev.ru 
616240Sigor@sysoev.ru     nxt_process_title(task, "%s", title);
617240Sigor@sysoev.ru }
618240Sigor@sysoev.ru 
619240Sigor@sysoev.ru 
620240Sigor@sysoev.ru static nxt_int_t
6211488St.nateldemoura@f5.com nxt_main_process_create(nxt_task_t *task, const nxt_process_init_t init)
622240Sigor@sysoev.ru {
6231488St.nateldemoura@f5.com     nxt_int_t           ret;
6241488St.nateldemoura@f5.com     nxt_runtime_t       *rt;
6251488St.nateldemoura@f5.com     nxt_process_t       *process;
6261488St.nateldemoura@f5.com     nxt_process_init_t  *pinit;
627240Sigor@sysoev.ru 
6281488St.nateldemoura@f5.com     rt = task->thread->runtime;
6291302St.nateldemoura@f5.com 
6301488St.nateldemoura@f5.com     process = nxt_main_process_new(task, rt);
6311488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
632368Svbart@nginx.com         return NXT_ERROR;
633368Svbart@nginx.com     }
634368Svbart@nginx.com 
6351488St.nateldemoura@f5.com     process->name = init.name;
6361488St.nateldemoura@f5.com     process->user_cred = &rt->user_cred;
637314Svbart@nginx.com 
6381488St.nateldemoura@f5.com     pinit = nxt_process_init(process);
6391488St.nateldemoura@f5.com     *pinit = init;
640314Svbart@nginx.com 
6411488St.nateldemoura@f5.com     ret = nxt_main_start_process(task, process);
6421488St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
6431488St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
644314Svbart@nginx.com     }
645314Svbart@nginx.com 
646314Svbart@nginx.com     return ret;
647240Sigor@sysoev.ru }
648240Sigor@sysoev.ru 
649240Sigor@sysoev.ru 
6501488St.nateldemoura@f5.com static nxt_process_t *
6511488St.nateldemoura@f5.com nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt)
652240Sigor@sysoev.ru {
6531488St.nateldemoura@f5.com     nxt_process_t  *process;
654240Sigor@sysoev.ru 
6551488St.nateldemoura@f5.com     process = nxt_runtime_process_new(rt);
6561488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
6571488St.nateldemoura@f5.com         return NULL;
658240Sigor@sysoev.ru     }
659240Sigor@sysoev.ru 
6601488St.nateldemoura@f5.com     process->mem_pool = nxt_mp_create(1024, 128, 256, 32);
6611488St.nateldemoura@f5.com     if (process->mem_pool == NULL) {
6621488St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6631488St.nateldemoura@f5.com         return NULL;
664240Sigor@sysoev.ru     }
665240Sigor@sysoev.ru 
6661488St.nateldemoura@f5.com     return process;
667240Sigor@sysoev.ru }
668240Sigor@sysoev.ru 
6691302St.nateldemoura@f5.com 
670240Sigor@sysoev.ru static nxt_int_t
6711488St.nateldemoura@f5.com nxt_main_start_process(nxt_task_t *task, nxt_process_t *process)
672240Sigor@sysoev.ru {
6731488St.nateldemoura@f5.com     nxt_mp_t            *tmp_mp;
6741182St.nateldemoura@f5.com     nxt_int_t           ret;
6751488St.nateldemoura@f5.com     nxt_pid_t           pid;
6761488St.nateldemoura@f5.com     nxt_port_t          *port;
677240Sigor@sysoev.ru     nxt_process_init_t  *init;
678240Sigor@sysoev.ru 
6791488St.nateldemoura@f5.com     init = nxt_process_init(process);
680240Sigor@sysoev.ru 
681240Sigor@sysoev.ru     port = nxt_port_new(task, 0, 0, init->type);
682240Sigor@sysoev.ru     if (nxt_slow_path(port == NULL)) {
683240Sigor@sysoev.ru         return NXT_ERROR;
684240Sigor@sysoev.ru     }
685240Sigor@sysoev.ru 
686240Sigor@sysoev.ru     nxt_process_port_add(task, process, port);
687240Sigor@sysoev.ru 
688240Sigor@sysoev.ru     ret = nxt_port_socket_init(task, port, 0);
689240Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
6901565St.nateldemoura@f5.com         goto free_port;
6911488St.nateldemoura@f5.com     }
6921488St.nateldemoura@f5.com 
6931488St.nateldemoura@f5.com     tmp_mp = nxt_mp_create(1024, 128, 256, 32);
6941565St.nateldemoura@f5.com     if (nxt_slow_path(tmp_mp == NULL)) {
6951565St.nateldemoura@f5.com         ret = NXT_ERROR;
6961565St.nateldemoura@f5.com 
6971565St.nateldemoura@f5.com         goto close_port;
6981488St.nateldemoura@f5.com     }
6991488St.nateldemoura@f5.com 
7001488St.nateldemoura@f5.com     if (init->prefork) {
7011488St.nateldemoura@f5.com         ret = init->prefork(task, process, tmp_mp);
7021488St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
7031565St.nateldemoura@f5.com             goto free_mempool;
7041488St.nateldemoura@f5.com         }
705240Sigor@sysoev.ru     }
706240Sigor@sysoev.ru 
707240Sigor@sysoev.ru     pid = nxt_process_create(task, process);
708240Sigor@sysoev.ru 
709240Sigor@sysoev.ru     switch (pid) {
710240Sigor@sysoev.ru 
711240Sigor@sysoev.ru     case -1:
7121565St.nateldemoura@f5.com         ret = NXT_ERROR;
7131488St.nateldemoura@f5.com         break;
714240Sigor@sysoev.ru 
715240Sigor@sysoev.ru     case 0:
7161488St.nateldemoura@f5.com         /* The child process: return to the event engine work queue loop. */
7171180Smax.romanov@nginx.com 
7181565St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
7191565St.nateldemoura@f5.com 
7201488St.nateldemoura@f5.com         ret = NXT_AGAIN;
7211488St.nateldemoura@f5.com         break;
722240Sigor@sysoev.ru 
723240Sigor@sysoev.ru     default:
724240Sigor@sysoev.ru         /* The main process created a new process. */
725240Sigor@sysoev.ru 
7261565St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
7271565St.nateldemoura@f5.com 
728240Sigor@sysoev.ru         nxt_port_read_close(port);
729240Sigor@sysoev.ru         nxt_port_write_enable(task, port);
730240Sigor@sysoev.ru 
7311488St.nateldemoura@f5.com         ret = NXT_OK;
7321488St.nateldemoura@f5.com         break;
733240Sigor@sysoev.ru     }
734240Sigor@sysoev.ru 
7351565St.nateldemoura@f5.com free_mempool:
7361565St.nateldemoura@f5.com 
7371565St.nateldemoura@f5.com     nxt_mp_destroy(tmp_mp);
7381565St.nateldemoura@f5.com 
7391565St.nateldemoura@f5.com close_port:
7401565St.nateldemoura@f5.com 
7411565St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
7421565St.nateldemoura@f5.com         nxt_port_close(task, port);
7431565St.nateldemoura@f5.com     }
7441565St.nateldemoura@f5.com 
7451565St.nateldemoura@f5.com free_port:
746240Sigor@sysoev.ru 
7471488St.nateldemoura@f5.com     nxt_port_use(task, port, -1);
748240Sigor@sysoev.ru 
7491488St.nateldemoura@f5.com     return ret;
750240Sigor@sysoev.ru }
751240Sigor@sysoev.ru 
752240Sigor@sysoev.ru 
753240Sigor@sysoev.ru static void
754240Sigor@sysoev.ru nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, void *data)
755240Sigor@sysoev.ru {
756240Sigor@sysoev.ru     nxt_debug(task, "sigterm handler signo:%d (%s)",
757240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
758240Sigor@sysoev.ru 
759240Sigor@sysoev.ru     /* TODO: fast exit. */
760240Sigor@sysoev.ru 
761240Sigor@sysoev.ru     nxt_exiting = 1;
762240Sigor@sysoev.ru 
763697Sigor@sysoev.ru     nxt_runtime_quit(task, 0);
764240Sigor@sysoev.ru }
765240Sigor@sysoev.ru 
766240Sigor@sysoev.ru 
767240Sigor@sysoev.ru static void
768240Sigor@sysoev.ru nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, void *data)
769240Sigor@sysoev.ru {
770240Sigor@sysoev.ru     nxt_debug(task, "sigquit handler signo:%d (%s)",
771240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
772240Sigor@sysoev.ru 
773240Sigor@sysoev.ru     /* TODO: graceful exit. */
774240Sigor@sysoev.ru 
775240Sigor@sysoev.ru     nxt_exiting = 1;
776240Sigor@sysoev.ru 
777697Sigor@sysoev.ru     nxt_runtime_quit(task, 0);
778240Sigor@sysoev.ru }
779240Sigor@sysoev.ru 
780240Sigor@sysoev.ru 
781240Sigor@sysoev.ru static void
782240Sigor@sysoev.ru nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, void *data)
783240Sigor@sysoev.ru {
784240Sigor@sysoev.ru     nxt_mp_t        *mp;
785240Sigor@sysoev.ru     nxt_int_t       ret;
786240Sigor@sysoev.ru     nxt_uint_t      n;
787631Svbart@nginx.com     nxt_port_t      *port;
788240Sigor@sysoev.ru     nxt_file_t      *file, *new_file;
789631Svbart@nginx.com     nxt_array_t     *new_files;
790240Sigor@sysoev.ru     nxt_runtime_t   *rt;
791240Sigor@sysoev.ru 
792240Sigor@sysoev.ru     nxt_log(task, NXT_LOG_NOTICE, "signal %d (%s) recevied, %s",
793240Sigor@sysoev.ru             (int) (uintptr_t) obj, data, "log files rotation");
794240Sigor@sysoev.ru 
795631Svbart@nginx.com     rt = task->thread->runtime;
796631Svbart@nginx.com 
797631Svbart@nginx.com     port = rt->port_by_type[NXT_PROCESS_ROUTER];
798631Svbart@nginx.com 
799631Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
800631Svbart@nginx.com         (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_ACCESS_LOG,
801631Svbart@nginx.com                                      -1, 0, 0, NULL);
802631Svbart@nginx.com     }
803631Svbart@nginx.com 
804240Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
805240Sigor@sysoev.ru     if (mp == NULL) {
806240Sigor@sysoev.ru         return;
807240Sigor@sysoev.ru     }
808240Sigor@sysoev.ru 
809240Sigor@sysoev.ru     n = nxt_list_nelts(rt->log_files);
810240Sigor@sysoev.ru 
811240Sigor@sysoev.ru     new_files = nxt_array_create(mp, n, sizeof(nxt_file_t));
812240Sigor@sysoev.ru     if (new_files == NULL) {
813240Sigor@sysoev.ru         nxt_mp_destroy(mp);
814240Sigor@sysoev.ru         return;
815240Sigor@sysoev.ru     }
816240Sigor@sysoev.ru 
817240Sigor@sysoev.ru     nxt_list_each(file, rt->log_files) {
818240Sigor@sysoev.ru 
819240Sigor@sysoev.ru         /* This allocation cannot fail. */
820240Sigor@sysoev.ru         new_file = nxt_array_add(new_files);
821240Sigor@sysoev.ru 
822240Sigor@sysoev.ru         new_file->name = file->name;
823240Sigor@sysoev.ru         new_file->fd = NXT_FILE_INVALID;
824564Svbart@nginx.com         new_file->log_level = NXT_LOG_ALERT;
825240Sigor@sysoev.ru 
826240Sigor@sysoev.ru         ret = nxt_file_open(task, new_file, O_WRONLY | O_APPEND, O_CREAT,
827240Sigor@sysoev.ru                             NXT_FILE_OWNER_ACCESS);
828240Sigor@sysoev.ru 
829240Sigor@sysoev.ru         if (ret != NXT_OK) {
830240Sigor@sysoev.ru             goto fail;
831240Sigor@sysoev.ru         }
832240Sigor@sysoev.ru 
833240Sigor@sysoev.ru     } nxt_list_loop;
834240Sigor@sysoev.ru 
835240Sigor@sysoev.ru     new_file = new_files->elts;
836240Sigor@sysoev.ru 
837240Sigor@sysoev.ru     ret = nxt_file_stderr(&new_file[0]);
838240Sigor@sysoev.ru 
839240Sigor@sysoev.ru     if (ret == NXT_OK) {
840240Sigor@sysoev.ru         n = 0;
841240Sigor@sysoev.ru 
842240Sigor@sysoev.ru         nxt_list_each(file, rt->log_files) {
843240Sigor@sysoev.ru 
844240Sigor@sysoev.ru             nxt_port_change_log_file(task, rt, n, new_file[n].fd);
845240Sigor@sysoev.ru             /*
846240Sigor@sysoev.ru              * The old log file descriptor must be closed at the moment
847240Sigor@sysoev.ru              * when no other threads use it.  dup2() allows to use the
848240Sigor@sysoev.ru              * old file descriptor for new log file.  This change is
849240Sigor@sysoev.ru              * performed atomically in the kernel.
850240Sigor@sysoev.ru              */
851240Sigor@sysoev.ru             (void) nxt_file_redirect(file, new_file[n].fd);
852240Sigor@sysoev.ru 
853240Sigor@sysoev.ru             n++;
854240Sigor@sysoev.ru 
855240Sigor@sysoev.ru         } nxt_list_loop;
856240Sigor@sysoev.ru 
857240Sigor@sysoev.ru         nxt_mp_destroy(mp);
858240Sigor@sysoev.ru         return;
8591008Szelenkov@nginx.com     }
860240Sigor@sysoev.ru 
861240Sigor@sysoev.ru fail:
862240Sigor@sysoev.ru 
863240Sigor@sysoev.ru     new_file = new_files->elts;
864240Sigor@sysoev.ru     n = new_files->nelts;
865240Sigor@sysoev.ru 
866240Sigor@sysoev.ru     while (n != 0) {
867240Sigor@sysoev.ru         if (new_file->fd != NXT_FILE_INVALID) {
868240Sigor@sysoev.ru             nxt_file_close(task, new_file);
869240Sigor@sysoev.ru         }
870240Sigor@sysoev.ru 
871240Sigor@sysoev.ru         new_file++;
872240Sigor@sysoev.ru         n--;
873240Sigor@sysoev.ru     }
874240Sigor@sysoev.ru 
875240Sigor@sysoev.ru     nxt_mp_destroy(mp);
876240Sigor@sysoev.ru }
877240Sigor@sysoev.ru 
878240Sigor@sysoev.ru 
879240Sigor@sysoev.ru static void
880240Sigor@sysoev.ru nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, void *data)
881240Sigor@sysoev.ru {
882240Sigor@sysoev.ru     int                    status;
883240Sigor@sysoev.ru     nxt_err_t              err;
884240Sigor@sysoev.ru     nxt_pid_t              pid;
885240Sigor@sysoev.ru 
886240Sigor@sysoev.ru     nxt_debug(task, "sigchld handler signo:%d (%s)",
887240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
888240Sigor@sysoev.ru 
889240Sigor@sysoev.ru     for ( ;; ) {
890240Sigor@sysoev.ru         pid = waitpid(-1, &status, WNOHANG);
891240Sigor@sysoev.ru 
892240Sigor@sysoev.ru         if (pid == -1) {
893240Sigor@sysoev.ru 
894240Sigor@sysoev.ru             switch (err = nxt_errno) {
895240Sigor@sysoev.ru 
896240Sigor@sysoev.ru             case NXT_ECHILD:
897240Sigor@sysoev.ru                 return;
898240Sigor@sysoev.ru 
899240Sigor@sysoev.ru             case NXT_EINTR:
900240Sigor@sysoev.ru                 continue;
901240Sigor@sysoev.ru 
902240Sigor@sysoev.ru             default:
903564Svbart@nginx.com                 nxt_alert(task, "waitpid() failed: %E", err);
904240Sigor@sysoev.ru                 return;
905240Sigor@sysoev.ru             }
906240Sigor@sysoev.ru         }
907240Sigor@sysoev.ru 
908240Sigor@sysoev.ru         nxt_debug(task, "waitpid(): %PI", pid);
909240Sigor@sysoev.ru 
910240Sigor@sysoev.ru         if (pid == 0) {
911240Sigor@sysoev.ru             return;
912240Sigor@sysoev.ru         }
913240Sigor@sysoev.ru 
914240Sigor@sysoev.ru         if (WTERMSIG(status)) {
915240Sigor@sysoev.ru #ifdef WCOREDUMP
916564Svbart@nginx.com             nxt_alert(task, "process %PI exited on signal %d%s",
917564Svbart@nginx.com                       pid, WTERMSIG(status),
918564Svbart@nginx.com                       WCOREDUMP(status) ? " (core dumped)" : "");
919240Sigor@sysoev.ru #else
920564Svbart@nginx.com             nxt_alert(task, "process %PI exited on signal %d",
921564Svbart@nginx.com                       pid, WTERMSIG(status));
922240Sigor@sysoev.ru #endif
923240Sigor@sysoev.ru 
924240Sigor@sysoev.ru         } else {
925240Sigor@sysoev.ru             nxt_trace(task, "process %PI exited with code %d",
926240Sigor@sysoev.ru                       pid, WEXITSTATUS(status));
927240Sigor@sysoev.ru         }
928240Sigor@sysoev.ru 
9291488St.nateldemoura@f5.com         nxt_main_cleanup_process(task, pid);
930240Sigor@sysoev.ru     }
931240Sigor@sysoev.ru }
932240Sigor@sysoev.ru 
933240Sigor@sysoev.ru 
934240Sigor@sysoev.ru static void
935944Sigor@sysoev.ru nxt_main_process_signal_handler(nxt_task_t *task, void *obj, void *data)
936944Sigor@sysoev.ru {
937944Sigor@sysoev.ru     nxt_trace(task, "signal signo:%d (%s) recevied, ignored",
938944Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
939944Sigor@sysoev.ru }
940944Sigor@sysoev.ru 
941944Sigor@sysoev.ru 
942944Sigor@sysoev.ru static void
9431488St.nateldemoura@f5.com nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid)
944240Sigor@sysoev.ru {
9451488St.nateldemoura@f5.com     int                 stream;
9461488St.nateldemoura@f5.com     nxt_int_t           ret;
9471488St.nateldemoura@f5.com     nxt_buf_t           *buf;
9481488St.nateldemoura@f5.com     nxt_port_t          *port;
9491488St.nateldemoura@f5.com     const char          *name;
9501488St.nateldemoura@f5.com     nxt_runtime_t       *rt;
9511488St.nateldemoura@f5.com     nxt_process_t       *process;
9521488St.nateldemoura@f5.com     nxt_process_init_t  init;
953240Sigor@sysoev.ru 
954240Sigor@sysoev.ru     rt = task->thread->runtime;
955240Sigor@sysoev.ru 
956240Sigor@sysoev.ru     process = nxt_runtime_process_find(rt, pid);
9571488St.nateldemoura@f5.com     if (!process) {
9581488St.nateldemoura@f5.com         return;
9591488St.nateldemoura@f5.com     }
960240Sigor@sysoev.ru 
9611579St.nateldemoura@f5.com     if (process->isolation.cleanup != NULL) {
9621579St.nateldemoura@f5.com         process->isolation.cleanup(task, process);
9631489St.nateldemoura@f5.com     }
9641489St.nateldemoura@f5.com 
9651488St.nateldemoura@f5.com     name = process->name;
9661488St.nateldemoura@f5.com     stream = process->stream;
9671488St.nateldemoura@f5.com     init = *((nxt_process_init_t *) nxt_process_init(process));
968366Smax.romanov@nginx.com 
9691488St.nateldemoura@f5.com     if (process->state == NXT_PROCESS_STATE_READY) {
9701488St.nateldemoura@f5.com         process->stream = 0;
9711488St.nateldemoura@f5.com     }
972240Sigor@sysoev.ru 
9731488St.nateldemoura@f5.com     nxt_process_close_ports(task, process);
9741302St.nateldemoura@f5.com 
9751488St.nateldemoura@f5.com     if (nxt_exiting) {
9761488St.nateldemoura@f5.com         if (rt->nprocesses <= 1) {
9771488St.nateldemoura@f5.com             nxt_runtime_quit(task, 0);
9781211Smax.romanov@nginx.com         }
9791211Smax.romanov@nginx.com 
9801488St.nateldemoura@f5.com         return;
981240Sigor@sysoev.ru     }
982754Smax.romanov@nginx.com 
983754Smax.romanov@nginx.com     nxt_runtime_process_each(rt, process) {
984754Smax.romanov@nginx.com 
9851488St.nateldemoura@f5.com         if (process->pid == nxt_pid
9861488St.nateldemoura@f5.com             || process->pid == pid
9871488St.nateldemoura@f5.com             || nxt_queue_is_empty(&process->ports))
9881488St.nateldemoura@f5.com         {
9891488St.nateldemoura@f5.com             continue;
9901488St.nateldemoura@f5.com         }
9911488St.nateldemoura@f5.com 
9921488St.nateldemoura@f5.com         port = nxt_process_port_first(process);
993754Smax.romanov@nginx.com 
9941488St.nateldemoura@f5.com         if (nxt_proc_remove_notify_matrix[init.type][port->type] == 0) {
9951488St.nateldemoura@f5.com             continue;
9961488St.nateldemoura@f5.com         }
9971488St.nateldemoura@f5.com 
9981488St.nateldemoura@f5.com         buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
9991488St.nateldemoura@f5.com                                    sizeof(pid));
1000754Smax.romanov@nginx.com 
10011488St.nateldemoura@f5.com         if (nxt_slow_path(buf == NULL)) {
10021488St.nateldemoura@f5.com             continue;
10031488St.nateldemoura@f5.com         }
10041488St.nateldemoura@f5.com 
10051488St.nateldemoura@f5.com         buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid));
10061488St.nateldemoura@f5.com 
10071488St.nateldemoura@f5.com         nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID, -1,
10081488St.nateldemoura@f5.com                               stream, 0, buf);
1009754Smax.romanov@nginx.com 
1010754Smax.romanov@nginx.com     } nxt_runtime_process_loop;
10111488St.nateldemoura@f5.com 
10121488St.nateldemoura@f5.com     if (init.restart) {
10131488St.nateldemoura@f5.com         ret = nxt_main_process_create(task, init);
10141488St.nateldemoura@f5.com         if (nxt_slow_path(ret == NXT_ERROR)) {
10151488St.nateldemoura@f5.com             nxt_alert(task, "failed to restart %s", name);
10161488St.nateldemoura@f5.com         }
10171488St.nateldemoura@f5.com     }
1018754Smax.romanov@nginx.com }
1019754Smax.romanov@nginx.com 
1020754Smax.romanov@nginx.com 
1021754Smax.romanov@nginx.com static void
1022240Sigor@sysoev.ru nxt_main_port_socket_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1023240Sigor@sysoev.ru {
1024240Sigor@sysoev.ru     size_t                  size;
1025240Sigor@sysoev.ru     nxt_int_t               ret;
1026240Sigor@sysoev.ru     nxt_buf_t               *b, *out;
1027240Sigor@sysoev.ru     nxt_port_t              *port;
1028240Sigor@sysoev.ru     nxt_sockaddr_t          *sa;
1029240Sigor@sysoev.ru     nxt_port_msg_type_t     type;
1030240Sigor@sysoev.ru     nxt_listening_socket_t  ls;
1031240Sigor@sysoev.ru     u_char                  message[2048];
1032240Sigor@sysoev.ru 
10331788Smax.romanov@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
10341788Smax.romanov@nginx.com                                  msg->port_msg.reply_port);
10351788Smax.romanov@nginx.com     if (nxt_slow_path(port == NULL)) {
10361788Smax.romanov@nginx.com         return;
10371788Smax.romanov@nginx.com     }
10381788Smax.romanov@nginx.com 
1039*1996St.nateldemoura@f5.com     if (nxt_slow_path(port->type != NXT_PROCESS_ROUTER)) {
1040*1996St.nateldemoura@f5.com         nxt_alert(task, "process %PI cannot create listener sockets",
1041*1996St.nateldemoura@f5.com                   msg->port_msg.pid);
1042*1996St.nateldemoura@f5.com 
1043*1996St.nateldemoura@f5.com         return;
1044*1996St.nateldemoura@f5.com     }
1045*1996St.nateldemoura@f5.com 
1046240Sigor@sysoev.ru     b = msg->buf;
1047240Sigor@sysoev.ru     sa = (nxt_sockaddr_t *) b->mem.pos;
1048240Sigor@sysoev.ru 
1049352Smax.romanov@nginx.com     /* TODO check b size and make plain */
1050352Smax.romanov@nginx.com 
1051240Sigor@sysoev.ru     ls.socket = -1;
1052240Sigor@sysoev.ru     ls.error = NXT_SOCKET_ERROR_SYSTEM;
1053240Sigor@sysoev.ru     ls.start = message;
1054240Sigor@sysoev.ru     ls.end = message + sizeof(message);
1055240Sigor@sysoev.ru 
1056240Sigor@sysoev.ru     nxt_debug(task, "listening socket \"%*s\"",
1057493Spluknet@nginx.com               (size_t) sa->length, nxt_sockaddr_start(sa));
1058240Sigor@sysoev.ru 
1059240Sigor@sysoev.ru     ret = nxt_main_listening_socket(sa, &ls);
1060240Sigor@sysoev.ru 
1061240Sigor@sysoev.ru     if (ret == NXT_OK) {
1062240Sigor@sysoev.ru         nxt_debug(task, "socket(\"%*s\"): %d",
1063493Spluknet@nginx.com                   (size_t) sa->length, nxt_sockaddr_start(sa), ls.socket);
1064240Sigor@sysoev.ru 
10651788Smax.romanov@nginx.com         out = NULL;
10661788Smax.romanov@nginx.com 
1067240Sigor@sysoev.ru         type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD;
1068240Sigor@sysoev.ru 
1069240Sigor@sysoev.ru     } else {
1070240Sigor@sysoev.ru         size = ls.end - ls.start;
1071240Sigor@sysoev.ru 
1072564Svbart@nginx.com         nxt_alert(task, "%*s", size, ls.start);
1073240Sigor@sysoev.ru 
1074342Smax.romanov@nginx.com         out = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
1075342Smax.romanov@nginx.com                                    size + 1);
10761788Smax.romanov@nginx.com         if (nxt_fast_path(out != NULL)) {
10771788Smax.romanov@nginx.com             *out->mem.free++ = (uint8_t) ls.error;
1078240Sigor@sysoev.ru 
10791788Smax.romanov@nginx.com             out->mem.free = nxt_cpymem(out->mem.free, ls.start, size);
10801788Smax.romanov@nginx.com         }
1081240Sigor@sysoev.ru 
1082240Sigor@sysoev.ru         type = NXT_PORT_MSG_RPC_ERROR;
1083240Sigor@sysoev.ru     }
1084240Sigor@sysoev.ru 
1085240Sigor@sysoev.ru     nxt_port_socket_write(task, port, type, ls.socket, msg->port_msg.stream,
1086240Sigor@sysoev.ru                           0, out);
1087240Sigor@sysoev.ru }
1088240Sigor@sysoev.ru 
1089240Sigor@sysoev.ru 
1090240Sigor@sysoev.ru static nxt_int_t
1091240Sigor@sysoev.ru nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls)
1092240Sigor@sysoev.ru {
1093240Sigor@sysoev.ru     nxt_err_t         err;
1094240Sigor@sysoev.ru     nxt_socket_t      s;
1095240Sigor@sysoev.ru 
1096240Sigor@sysoev.ru     const socklen_t   length = sizeof(int);
1097240Sigor@sysoev.ru     static const int  enable = 1;
1098240Sigor@sysoev.ru 
1099240Sigor@sysoev.ru     s = socket(sa->u.sockaddr.sa_family, sa->type, 0);
1100240Sigor@sysoev.ru 
1101240Sigor@sysoev.ru     if (nxt_slow_path(s == -1)) {
1102240Sigor@sysoev.ru         err = nxt_errno;
1103240Sigor@sysoev.ru 
1104240Sigor@sysoev.ru #if (NXT_INET6)
1105240Sigor@sysoev.ru 
1106240Sigor@sysoev.ru         if (err == EAFNOSUPPORT && sa->u.sockaddr.sa_family == AF_INET6) {
1107240Sigor@sysoev.ru             ls->error = NXT_SOCKET_ERROR_NOINET6;
1108240Sigor@sysoev.ru         }
1109240Sigor@sysoev.ru 
1110240Sigor@sysoev.ru #endif
1111240Sigor@sysoev.ru 
1112240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end,
1113240Sigor@sysoev.ru                               "socket(\\\"%*s\\\") failed %E",
1114493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa), err);
1115240Sigor@sysoev.ru 
1116240Sigor@sysoev.ru         return NXT_ERROR;
1117240Sigor@sysoev.ru     }
1118240Sigor@sysoev.ru 
1119240Sigor@sysoev.ru     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, length) != 0) {
1120240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end,
1121240Sigor@sysoev.ru                               "setsockopt(\\\"%*s\\\", SO_REUSEADDR) failed %E",
1122493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa),
1123493Spluknet@nginx.com                               nxt_errno);
1124240Sigor@sysoev.ru         goto fail;
1125240Sigor@sysoev.ru     }
1126240Sigor@sysoev.ru 
1127240Sigor@sysoev.ru #if (NXT_INET6)
1128240Sigor@sysoev.ru 
1129240Sigor@sysoev.ru     if (sa->u.sockaddr.sa_family == AF_INET6) {
1130240Sigor@sysoev.ru 
1131240Sigor@sysoev.ru         if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, length) != 0) {
1132240Sigor@sysoev.ru             ls->end = nxt_sprintf(ls->start, ls->end,
1133240Sigor@sysoev.ru                                "setsockopt(\\\"%*s\\\", IPV6_V6ONLY) failed %E",
1134493Spluknet@nginx.com                                (size_t) sa->length, nxt_sockaddr_start(sa),
1135493Spluknet@nginx.com                                nxt_errno);
1136240Sigor@sysoev.ru             goto fail;
1137240Sigor@sysoev.ru         }
1138240Sigor@sysoev.ru     }
1139240Sigor@sysoev.ru 
1140240Sigor@sysoev.ru #endif
1141240Sigor@sysoev.ru 
1142240Sigor@sysoev.ru     if (bind(s, &sa->u.sockaddr, sa->socklen) != 0) {
1143240Sigor@sysoev.ru         err = nxt_errno;
1144240Sigor@sysoev.ru 
1145240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
1146240Sigor@sysoev.ru 
1147240Sigor@sysoev.ru         if (sa->u.sockaddr.sa_family == AF_UNIX) {
1148240Sigor@sysoev.ru             switch (err) {
1149240Sigor@sysoev.ru 
1150240Sigor@sysoev.ru             case EACCES:
1151240Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_ACCESS;
1152240Sigor@sysoev.ru                 break;
1153240Sigor@sysoev.ru 
1154240Sigor@sysoev.ru             case ENOENT:
1155240Sigor@sysoev.ru             case ENOTDIR:
1156240Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_PATH;
1157240Sigor@sysoev.ru                 break;
1158240Sigor@sysoev.ru             }
1159240Sigor@sysoev.ru 
1160908Sigor@sysoev.ru         } else
1161908Sigor@sysoev.ru #endif
1162908Sigor@sysoev.ru         {
1163908Sigor@sysoev.ru             switch (err) {
1164240Sigor@sysoev.ru 
1165908Sigor@sysoev.ru             case EACCES:
1166908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_PORT;
1167908Sigor@sysoev.ru                 break;
1168240Sigor@sysoev.ru 
1169908Sigor@sysoev.ru             case EADDRINUSE:
1170908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_INUSE;
1171908Sigor@sysoev.ru                 break;
1172240Sigor@sysoev.ru 
1173908Sigor@sysoev.ru             case EADDRNOTAVAIL:
1174908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_NOADDR;
1175908Sigor@sysoev.ru                 break;
1176908Sigor@sysoev.ru             }
1177240Sigor@sysoev.ru         }
1178240Sigor@sysoev.ru 
1179240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end, "bind(\\\"%*s\\\") failed %E",
1180493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa), err);
1181240Sigor@sysoev.ru         goto fail;
1182240Sigor@sysoev.ru     }
1183240Sigor@sysoev.ru 
1184240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
1185240Sigor@sysoev.ru 
1186240Sigor@sysoev.ru     if (sa->u.sockaddr.sa_family == AF_UNIX) {
1187240Sigor@sysoev.ru         char     *filename;
1188240Sigor@sysoev.ru         mode_t   access;
1189240Sigor@sysoev.ru 
1190240Sigor@sysoev.ru         filename = sa->u.sockaddr_un.sun_path;
1191240Sigor@sysoev.ru         access = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1192240Sigor@sysoev.ru 
1193240Sigor@sysoev.ru         if (chmod(filename, access) != 0) {
1194240Sigor@sysoev.ru             ls->end = nxt_sprintf(ls->start, ls->end,
1195494Spluknet@nginx.com                                   "chmod(\\\"%s\\\") failed %E",
1196240Sigor@sysoev.ru                                   filename, nxt_errno);
1197240Sigor@sysoev.ru             goto fail;
1198240Sigor@sysoev.ru         }
1199240Sigor@sysoev.ru     }
1200240Sigor@sysoev.ru 
1201240Sigor@sysoev.ru #endif
1202240Sigor@sysoev.ru 
1203240Sigor@sysoev.ru     ls->socket = s;
1204240Sigor@sysoev.ru 
1205240Sigor@sysoev.ru     return NXT_OK;
1206240Sigor@sysoev.ru 
1207240Sigor@sysoev.ru fail:
1208240Sigor@sysoev.ru 
1209240Sigor@sysoev.ru     (void) close(s);
1210240Sigor@sysoev.ru 
1211240Sigor@sysoev.ru     return NXT_ERROR;
1212240Sigor@sysoev.ru }
1213240Sigor@sysoev.ru 
1214240Sigor@sysoev.ru 
1215240Sigor@sysoev.ru static nxt_conf_map_t  nxt_app_lang_module_map[] = {
1216240Sigor@sysoev.ru     {
1217240Sigor@sysoev.ru         nxt_string("type"),
1218356Svbart@nginx.com         NXT_CONF_MAP_INT,
1219240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, type),
1220240Sigor@sysoev.ru     },
1221240Sigor@sysoev.ru 
1222240Sigor@sysoev.ru     {
1223240Sigor@sysoev.ru         nxt_string("version"),
1224354Svbart@nginx.com         NXT_CONF_MAP_CSTRZ,
1225240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, version),
1226240Sigor@sysoev.ru     },
1227240Sigor@sysoev.ru 
1228240Sigor@sysoev.ru     {
1229240Sigor@sysoev.ru         nxt_string("file"),
1230240Sigor@sysoev.ru         NXT_CONF_MAP_CSTRZ,
1231240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, file),
1232240Sigor@sysoev.ru     },
1233240Sigor@sysoev.ru };
1234240Sigor@sysoev.ru 
1235240Sigor@sysoev.ru 
12361489St.nateldemoura@f5.com static nxt_conf_map_t  nxt_app_lang_mounts_map[] = {
12371489St.nateldemoura@f5.com     {
12381489St.nateldemoura@f5.com         nxt_string("src"),
12391489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
12401489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, src),
12411489St.nateldemoura@f5.com     },
12421489St.nateldemoura@f5.com     {
12431489St.nateldemoura@f5.com         nxt_string("dst"),
12441489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
12451489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, dst),
12461489St.nateldemoura@f5.com     },
12471489St.nateldemoura@f5.com     {
12481673St.nateldemoura@f5.com         nxt_string("name"),
12491489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
12501673St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, name),
12511673St.nateldemoura@f5.com     },
12521673St.nateldemoura@f5.com     {
12531673St.nateldemoura@f5.com         nxt_string("type"),
12541673St.nateldemoura@f5.com         NXT_CONF_MAP_INT,
12551673St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, type),
12561489St.nateldemoura@f5.com     },
12571489St.nateldemoura@f5.com     {
12581489St.nateldemoura@f5.com         nxt_string("flags"),
12591489St.nateldemoura@f5.com         NXT_CONF_MAP_INT,
12601489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, flags),
12611489St.nateldemoura@f5.com     },
12621489St.nateldemoura@f5.com     {
12631489St.nateldemoura@f5.com         nxt_string("data"),
12641489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
12651489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, data),
12661489St.nateldemoura@f5.com     },
12671489St.nateldemoura@f5.com };
12681489St.nateldemoura@f5.com 
12691489St.nateldemoura@f5.com 
1270240Sigor@sysoev.ru static void
1271240Sigor@sysoev.ru nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1272240Sigor@sysoev.ru {
12731489St.nateldemoura@f5.com     uint32_t               index, jindex, nmounts;
1274240Sigor@sysoev.ru     nxt_mp_t               *mp;
1275240Sigor@sysoev.ru     nxt_int_t              ret;
1276240Sigor@sysoev.ru     nxt_buf_t              *b;
1277549Svbart@nginx.com     nxt_port_t             *port;
1278240Sigor@sysoev.ru     nxt_runtime_t          *rt;
12791489St.nateldemoura@f5.com     nxt_fs_mount_t         *mnt;
12801489St.nateldemoura@f5.com     nxt_conf_value_t       *conf, *root, *value, *mounts;
1281240Sigor@sysoev.ru     nxt_app_lang_module_t  *lang;
1282240Sigor@sysoev.ru 
12831182St.nateldemoura@f5.com     static nxt_str_t root_path = nxt_string("/");
12841489St.nateldemoura@f5.com     static nxt_str_t mounts_name = nxt_string("mounts");
1285240Sigor@sysoev.ru 
1286240Sigor@sysoev.ru     rt = task->thread->runtime;
1287240Sigor@sysoev.ru 
1288240Sigor@sysoev.ru     if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) {
1289*1996St.nateldemoura@f5.com         nxt_alert(task, "process %PI cannot send modules", msg->port_msg.pid);
1290240Sigor@sysoev.ru         return;
1291240Sigor@sysoev.ru     }
1292240Sigor@sysoev.ru 
12931211Smax.romanov@nginx.com     if (nxt_exiting) {
12941211Smax.romanov@nginx.com         nxt_debug(task, "ignoring discovered modules, exiting");
12951211Smax.romanov@nginx.com         return;
12961211Smax.romanov@nginx.com     }
12971211Smax.romanov@nginx.com 
1298549Svbart@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1299549Svbart@nginx.com                                  msg->port_msg.reply_port);
1300549Svbart@nginx.com 
1301549Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
1302549Svbart@nginx.com         (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1,
1303549Svbart@nginx.com                                      msg->port_msg.stream, 0, NULL);
1304549Svbart@nginx.com     }
1305549Svbart@nginx.com 
1306240Sigor@sysoev.ru     b = msg->buf;
1307240Sigor@sysoev.ru 
1308240Sigor@sysoev.ru     if (b == NULL) {
1309240Sigor@sysoev.ru         return;
1310240Sigor@sysoev.ru     }
1311240Sigor@sysoev.ru 
1312240Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
1313240Sigor@sysoev.ru     if (mp == NULL) {
1314240Sigor@sysoev.ru         return;
1315240Sigor@sysoev.ru     }
1316240Sigor@sysoev.ru 
1317352Smax.romanov@nginx.com     b = nxt_buf_chk_make_plain(mp, b, msg->size);
1318352Smax.romanov@nginx.com 
1319352Smax.romanov@nginx.com     if (b == NULL) {
1320352Smax.romanov@nginx.com         return;
1321352Smax.romanov@nginx.com     }
1322352Smax.romanov@nginx.com 
1323352Smax.romanov@nginx.com     nxt_debug(task, "application languages: \"%*s\"",
1324352Smax.romanov@nginx.com               b->mem.free - b->mem.pos, b->mem.pos);
1325352Smax.romanov@nginx.com 
1326240Sigor@sysoev.ru     conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL);
1327240Sigor@sysoev.ru     if (conf == NULL) {
1328240Sigor@sysoev.ru         goto fail;
1329240Sigor@sysoev.ru     }
1330240Sigor@sysoev.ru 
1331240Sigor@sysoev.ru     root = nxt_conf_get_path(conf, &root_path);
1332240Sigor@sysoev.ru     if (root == NULL) {
1333240Sigor@sysoev.ru         goto fail;
1334240Sigor@sysoev.ru     }
1335240Sigor@sysoev.ru 
1336240Sigor@sysoev.ru     for (index = 0; /* void */ ; index++) {
1337240Sigor@sysoev.ru         value = nxt_conf_get_array_element(root, index);
1338240Sigor@sysoev.ru         if (value == NULL) {
1339240Sigor@sysoev.ru             break;
1340240Sigor@sysoev.ru         }
1341240Sigor@sysoev.ru 
13421489St.nateldemoura@f5.com         lang = nxt_array_zero_add(rt->languages);
1343240Sigor@sysoev.ru         if (lang == NULL) {
1344240Sigor@sysoev.ru             goto fail;
1345240Sigor@sysoev.ru         }
1346240Sigor@sysoev.ru 
1347240Sigor@sysoev.ru         lang->module = NULL;
1348240Sigor@sysoev.ru 
1349240Sigor@sysoev.ru         ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map,
1350240Sigor@sysoev.ru                                   nxt_nitems(nxt_app_lang_module_map), lang);
1351240Sigor@sysoev.ru 
1352240Sigor@sysoev.ru         if (ret != NXT_OK) {
1353240Sigor@sysoev.ru             goto fail;
1354240Sigor@sysoev.ru         }
1355240Sigor@sysoev.ru 
13561489St.nateldemoura@f5.com         mounts = nxt_conf_get_object_member(value, &mounts_name, NULL);
13571489St.nateldemoura@f5.com         if (mounts == NULL) {
13581489St.nateldemoura@f5.com             nxt_alert(task, "missing mounts from discovery message.");
13591489St.nateldemoura@f5.com             goto fail;
13601489St.nateldemoura@f5.com         }
13611489St.nateldemoura@f5.com 
13621489St.nateldemoura@f5.com         if (nxt_conf_type(mounts) != NXT_CONF_ARRAY) {
13631489St.nateldemoura@f5.com             nxt_alert(task, "invalid mounts type from discovery message.");
13641489St.nateldemoura@f5.com             goto fail;
13651489St.nateldemoura@f5.com         }
13661489St.nateldemoura@f5.com 
13671489St.nateldemoura@f5.com         nmounts = nxt_conf_array_elements_count(mounts);
13681489St.nateldemoura@f5.com 
13691489St.nateldemoura@f5.com         lang->mounts = nxt_array_create(rt->mem_pool, nmounts,
13701489St.nateldemoura@f5.com                                         sizeof(nxt_fs_mount_t));
13711489St.nateldemoura@f5.com 
13721489St.nateldemoura@f5.com         if (lang->mounts == NULL) {
13731489St.nateldemoura@f5.com             goto fail;
13741489St.nateldemoura@f5.com         }
13751489St.nateldemoura@f5.com 
13761489St.nateldemoura@f5.com         for (jindex = 0; /* */; jindex++) {
13771489St.nateldemoura@f5.com             value = nxt_conf_get_array_element(mounts, jindex);
13781489St.nateldemoura@f5.com             if (value == NULL) {
13791489St.nateldemoura@f5.com                 break;
13801489St.nateldemoura@f5.com             }
13811489St.nateldemoura@f5.com 
13821489St.nateldemoura@f5.com             mnt = nxt_array_zero_add(lang->mounts);
13831489St.nateldemoura@f5.com             if (mnt == NULL) {
13841489St.nateldemoura@f5.com                 goto fail;
13851489St.nateldemoura@f5.com             }
13861489St.nateldemoura@f5.com 
13871585St.nateldemoura@f5.com             mnt->builtin = 1;
13881673St.nateldemoura@f5.com             mnt->deps = 1;
13891585St.nateldemoura@f5.com 
13901489St.nateldemoura@f5.com             ret = nxt_conf_map_object(rt->mem_pool, value,
13911489St.nateldemoura@f5.com                                       nxt_app_lang_mounts_map,
13921489St.nateldemoura@f5.com                                       nxt_nitems(nxt_app_lang_mounts_map), mnt);
13931489St.nateldemoura@f5.com 
13941489St.nateldemoura@f5.com             if (ret != NXT_OK) {
13951489St.nateldemoura@f5.com                 goto fail;
13961489St.nateldemoura@f5.com             }
13971489St.nateldemoura@f5.com         }
13981489St.nateldemoura@f5.com 
13991489St.nateldemoura@f5.com         nxt_debug(task, "lang %d %s \"%s\" (%d mounts)",
14001489St.nateldemoura@f5.com                   lang->type, lang->version, lang->file, lang->mounts->nelts);
1401240Sigor@sysoev.ru     }
1402240Sigor@sysoev.ru 
1403240Sigor@sysoev.ru     qsort(rt->languages->elts, rt->languages->nelts,
1404240Sigor@sysoev.ru           sizeof(nxt_app_lang_module_t), nxt_app_lang_compare);
1405240Sigor@sysoev.ru 
1406240Sigor@sysoev.ru fail:
1407240Sigor@sysoev.ru 
1408240Sigor@sysoev.ru     nxt_mp_destroy(mp);
1409240Sigor@sysoev.ru 
14101488St.nateldemoura@f5.com     ret = nxt_main_process_create(task, nxt_controller_process);
14111488St.nateldemoura@f5.com     if (ret == NXT_OK) {
14121488St.nateldemoura@f5.com         ret = nxt_main_process_create(task, nxt_router_process);
14131488St.nateldemoura@f5.com     }
1414240Sigor@sysoev.ru 
14151488St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
14161488St.nateldemoura@f5.com         nxt_exiting = 1;
14171488St.nateldemoura@f5.com 
14181488St.nateldemoura@f5.com         nxt_runtime_quit(task, 1);
1419240Sigor@sysoev.ru     }
1420240Sigor@sysoev.ru }
1421240Sigor@sysoev.ru 
1422240Sigor@sysoev.ru 
1423240Sigor@sysoev.ru static int nxt_cdecl
1424240Sigor@sysoev.ru nxt_app_lang_compare(const void *v1, const void *v2)
1425240Sigor@sysoev.ru {
1426240Sigor@sysoev.ru     int                          n;
1427240Sigor@sysoev.ru     const nxt_app_lang_module_t  *lang1, *lang2;
1428240Sigor@sysoev.ru 
1429240Sigor@sysoev.ru     lang1 = v1;
1430240Sigor@sysoev.ru     lang2 = v2;
1431240Sigor@sysoev.ru 
1432356Svbart@nginx.com     n = lang1->type - lang2->type;
1433258Sigor@sysoev.ru 
1434258Sigor@sysoev.ru     if (n != 0) {
1435258Sigor@sysoev.ru         return n;
1436258Sigor@sysoev.ru     }
1437258Sigor@sysoev.ru 
1438354Svbart@nginx.com     n = nxt_strverscmp(lang1->version, lang2->version);
1439240Sigor@sysoev.ru 
1440240Sigor@sysoev.ru     /* Negate result to move higher versions to the beginning. */
1441240Sigor@sysoev.ru 
1442240Sigor@sysoev.ru     return -n;
1443240Sigor@sysoev.ru }
1444314Svbart@nginx.com 
1445314Svbart@nginx.com 
1446314Svbart@nginx.com static void
1447314Svbart@nginx.com nxt_main_port_conf_store_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1448314Svbart@nginx.com {
14491787Smax.romanov@nginx.com     void           *p;
14501969Sz.hong@f5.com     size_t         n, size;
1451314Svbart@nginx.com     nxt_int_t      ret;
1452*1996St.nateldemoura@f5.com     nxt_port_t     *ctl_port;
1453314Svbart@nginx.com     nxt_runtime_t  *rt;
14541969Sz.hong@f5.com     u_char         ver[NXT_INT_T_LEN];
1455314Svbart@nginx.com 
1456*1996St.nateldemoura@f5.com     rt = task->thread->runtime;
1457*1996St.nateldemoura@f5.com 
1458*1996St.nateldemoura@f5.com     ctl_port = rt->port_by_type[NXT_PROCESS_CONTROLLER];
1459*1996St.nateldemoura@f5.com 
1460*1996St.nateldemoura@f5.com     if (nxt_slow_path(msg->port_msg.pid != ctl_port->pid)) {
1461*1996St.nateldemoura@f5.com         nxt_alert(task, "process %PI cannot store conf", msg->port_msg.pid);
1462*1996St.nateldemoura@f5.com         return;
1463*1996St.nateldemoura@f5.com     }
1464*1996St.nateldemoura@f5.com 
14651787Smax.romanov@nginx.com     p = MAP_FAILED;
14661787Smax.romanov@nginx.com 
14671787Smax.romanov@nginx.com     /*
14681787Smax.romanov@nginx.com      * Ancient compilers like gcc 4.8.5 on CentOS 7 wants 'size' to be
14691787Smax.romanov@nginx.com      * initialized in 'cleanup' section.
14701787Smax.romanov@nginx.com      */
14711787Smax.romanov@nginx.com     size = 0;
14721787Smax.romanov@nginx.com 
14731787Smax.romanov@nginx.com     if (nxt_slow_path(msg->fd[0] == -1)) {
14741787Smax.romanov@nginx.com         nxt_alert(task, "conf_store_handler: invalid shm fd");
14751787Smax.romanov@nginx.com         goto error;
14761787Smax.romanov@nginx.com     }
14771787Smax.romanov@nginx.com 
14781787Smax.romanov@nginx.com     if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) {
14791787Smax.romanov@nginx.com         nxt_alert(task, "conf_store_handler: unexpected buffer size (%d)",
14801787Smax.romanov@nginx.com                   (int) nxt_buf_mem_used_size(&msg->buf->mem));
14811787Smax.romanov@nginx.com         goto error;
14821787Smax.romanov@nginx.com     }
14831787Smax.romanov@nginx.com 
14841787Smax.romanov@nginx.com     nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t));
14851787Smax.romanov@nginx.com 
14861787Smax.romanov@nginx.com     p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd[0], 0);
14871787Smax.romanov@nginx.com 
14881787Smax.romanov@nginx.com     nxt_fd_close(msg->fd[0]);
14891787Smax.romanov@nginx.com     msg->fd[0] = -1;
14901787Smax.romanov@nginx.com 
14911787Smax.romanov@nginx.com     if (nxt_slow_path(p == MAP_FAILED)) {
14921787Smax.romanov@nginx.com         goto error;
14931787Smax.romanov@nginx.com     }
14941787Smax.romanov@nginx.com 
14951787Smax.romanov@nginx.com     nxt_debug(task, "conf_store_handler(%uz): %*s", size, size, p);
14961787Smax.romanov@nginx.com 
14971969Sz.hong@f5.com     if (nxt_conf_ver != NXT_VERNUM) {
14981969Sz.hong@f5.com         n = nxt_sprintf(ver, ver + NXT_INT_T_LEN, "%d", NXT_VERNUM) - ver;
1499314Svbart@nginx.com 
15001969Sz.hong@f5.com         ret = nxt_main_file_store(task, rt->ver_tmp, rt->ver, ver, n);
15011969Sz.hong@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
15021969Sz.hong@f5.com             goto error;
15031969Sz.hong@f5.com         }
15041969Sz.hong@f5.com 
15051969Sz.hong@f5.com         nxt_conf_ver = NXT_VERNUM;
1506314Svbart@nginx.com     }
1507314Svbart@nginx.com 
15081969Sz.hong@f5.com     ret = nxt_main_file_store(task, rt->conf_tmp, rt->conf, p, size);
1509314Svbart@nginx.com 
1510314Svbart@nginx.com     if (nxt_fast_path(ret == NXT_OK)) {
15111787Smax.romanov@nginx.com         goto cleanup;
1512314Svbart@nginx.com     }
1513314Svbart@nginx.com 
1514314Svbart@nginx.com error:
1515314Svbart@nginx.com 
1516564Svbart@nginx.com     nxt_alert(task, "failed to store current configuration");
15171787Smax.romanov@nginx.com 
15181787Smax.romanov@nginx.com cleanup:
15191787Smax.romanov@nginx.com 
15201787Smax.romanov@nginx.com     if (p != MAP_FAILED) {
15211787Smax.romanov@nginx.com         nxt_mem_munmap(p, size);
15221787Smax.romanov@nginx.com     }
15231787Smax.romanov@nginx.com 
15241787Smax.romanov@nginx.com     if (msg->fd[0] != -1) {
15251787Smax.romanov@nginx.com         nxt_fd_close(msg->fd[0]);
15261787Smax.romanov@nginx.com         msg->fd[0] = -1;
15271787Smax.romanov@nginx.com     }
1528314Svbart@nginx.com }
1529630Svbart@nginx.com 
1530630Svbart@nginx.com 
15311969Sz.hong@f5.com static nxt_int_t
15321969Sz.hong@f5.com nxt_main_file_store(nxt_task_t *task, const char *tmp_name, const char *name,
15331969Sz.hong@f5.com     u_char *buf, size_t size)
15341969Sz.hong@f5.com {
15351969Sz.hong@f5.com     ssize_t     n;
15361969Sz.hong@f5.com     nxt_int_t   ret;
15371969Sz.hong@f5.com     nxt_file_t  file;
15381969Sz.hong@f5.com 
15391969Sz.hong@f5.com     nxt_memzero(&file, sizeof(nxt_file_t));
15401969Sz.hong@f5.com 
15411969Sz.hong@f5.com     file.name = (nxt_file_name_t *) name;
15421969Sz.hong@f5.com 
15431969Sz.hong@f5.com     ret = nxt_file_open(task, &file, NXT_FILE_WRONLY, NXT_FILE_TRUNCATE,
15441969Sz.hong@f5.com                         NXT_FILE_OWNER_ACCESS);
15451969Sz.hong@f5.com     if (nxt_slow_path(ret != NXT_OK)) {
15461969Sz.hong@f5.com         return NXT_ERROR;
15471969Sz.hong@f5.com     }
15481969Sz.hong@f5.com 
15491969Sz.hong@f5.com     n = nxt_file_write(&file, buf, size, 0);
15501969Sz.hong@f5.com 
15511969Sz.hong@f5.com     nxt_file_close(task, &file);
15521969Sz.hong@f5.com 
15531969Sz.hong@f5.com     if (nxt_slow_path(n != (ssize_t) size)) {
15541969Sz.hong@f5.com         (void) nxt_file_delete(file.name);
15551969Sz.hong@f5.com         return NXT_ERROR;
15561969Sz.hong@f5.com     }
15571969Sz.hong@f5.com 
15581969Sz.hong@f5.com     return nxt_file_rename(file.name, (nxt_file_name_t *) name);
15591969Sz.hong@f5.com }
15601969Sz.hong@f5.com 
15611969Sz.hong@f5.com 
1562630Svbart@nginx.com static void
1563630Svbart@nginx.com nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1564630Svbart@nginx.com {
1565630Svbart@nginx.com     u_char               *path;
1566630Svbart@nginx.com     nxt_int_t            ret;
1567630Svbart@nginx.com     nxt_file_t           file;
1568630Svbart@nginx.com     nxt_port_t           *port;
1569630Svbart@nginx.com     nxt_port_msg_type_t  type;
1570630Svbart@nginx.com 
1571630Svbart@nginx.com     nxt_debug(task, "opening access log file");
1572630Svbart@nginx.com 
1573630Svbart@nginx.com     path = msg->buf->mem.pos;
1574630Svbart@nginx.com 
1575630Svbart@nginx.com     nxt_memzero(&file, sizeof(nxt_file_t));
1576630Svbart@nginx.com 
1577630Svbart@nginx.com     file.name = (nxt_file_name_t *) path;
1578630Svbart@nginx.com     file.log_level = NXT_LOG_ERR;
1579630Svbart@nginx.com 
1580630Svbart@nginx.com     ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT,
1581630Svbart@nginx.com                         NXT_FILE_OWNER_ACCESS);
1582630Svbart@nginx.com 
1583630Svbart@nginx.com     type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD
1584630Svbart@nginx.com                            : NXT_PORT_MSG_RPC_ERROR;
1585630Svbart@nginx.com 
1586630Svbart@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1587630Svbart@nginx.com                                  msg->port_msg.reply_port);
1588630Svbart@nginx.com 
1589630Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
1590630Svbart@nginx.com         (void) nxt_port_socket_write(task, port, type, file.fd,
1591630Svbart@nginx.com                                      msg->port_msg.stream, 0, NULL);
1592630Svbart@nginx.com     }
1593630Svbart@nginx.com }
1594