xref: /unit/src/nxt_main_process.c (revision 1759)
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"),
185*1759Svbart@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     {
2141681Smax.romanov@nginx.com         nxt_string("thread_stack_size"),
2151681Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2161681Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.thread_stack_size),
2171681Smax.romanov@nginx.com     },
218510Salexander.borisov@nginx.com };
219240Sigor@sysoev.ru 
220510Salexander.borisov@nginx.com 
221546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_php_app_conf[] = {
222240Sigor@sysoev.ru     {
2231473Svbart@nginx.com         nxt_string("targets"),
2241473Svbart@nginx.com         NXT_CONF_MAP_PTR,
2251473Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.php.targets),
226240Sigor@sysoev.ru     },
227687Svbart@nginx.com 
228687Svbart@nginx.com     {
229687Svbart@nginx.com         nxt_string("options"),
230687Svbart@nginx.com         NXT_CONF_MAP_PTR,
231687Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.php.options),
232687Svbart@nginx.com     },
233510Salexander.borisov@nginx.com };
234240Sigor@sysoev.ru 
235510Salexander.borisov@nginx.com 
236546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_perl_app_conf[] = {
237510Salexander.borisov@nginx.com     {
238510Salexander.borisov@nginx.com         nxt_string("script"),
239510Salexander.borisov@nginx.com         NXT_CONF_MAP_CSTRZ,
240510Salexander.borisov@nginx.com         offsetof(nxt_common_app_conf_t, u.perl.script),
241510Salexander.borisov@nginx.com     },
2421689Smax.romanov@nginx.com 
2431689Smax.romanov@nginx.com     {
2441689Smax.romanov@nginx.com         nxt_string("threads"),
2451689Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2461689Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.perl.threads),
2471689Smax.romanov@nginx.com     },
2481689Smax.romanov@nginx.com 
2491689Smax.romanov@nginx.com     {
2501689Smax.romanov@nginx.com         nxt_string("thread_stack_size"),
2511689Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2521689Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.perl.thread_stack_size),
2531689Smax.romanov@nginx.com     },
254510Salexander.borisov@nginx.com };
255510Salexander.borisov@nginx.com 
256510Salexander.borisov@nginx.com 
257584Salexander.borisov@nginx.com static nxt_conf_map_t  nxt_ruby_app_conf[] = {
258584Salexander.borisov@nginx.com     {
259584Salexander.borisov@nginx.com         nxt_string("script"),
260584Salexander.borisov@nginx.com         NXT_CONF_MAP_STR,
261584Salexander.borisov@nginx.com         offsetof(nxt_common_app_conf_t, u.ruby.script),
262584Salexander.borisov@nginx.com     },
2631687Smax.romanov@nginx.com     {
2641687Smax.romanov@nginx.com         nxt_string("threads"),
2651687Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2661687Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.ruby.threads),
2671687Smax.romanov@nginx.com     },
268584Salexander.borisov@nginx.com };
269584Salexander.borisov@nginx.com 
270584Salexander.borisov@nginx.com 
271977Smax.romanov@gmail.com static nxt_conf_map_t  nxt_java_app_conf[] = {
272977Smax.romanov@gmail.com     {
273977Smax.romanov@gmail.com         nxt_string("classpath"),
274977Smax.romanov@gmail.com         NXT_CONF_MAP_PTR,
275977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.classpath),
276977Smax.romanov@gmail.com     },
277977Smax.romanov@gmail.com     {
278977Smax.romanov@gmail.com         nxt_string("webapp"),
279977Smax.romanov@gmail.com         NXT_CONF_MAP_CSTRZ,
280977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.webapp),
281977Smax.romanov@gmail.com     },
282977Smax.romanov@gmail.com     {
283977Smax.romanov@gmail.com         nxt_string("options"),
284977Smax.romanov@gmail.com         NXT_CONF_MAP_PTR,
285977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.options),
286977Smax.romanov@gmail.com     },
287977Smax.romanov@gmail.com     {
288977Smax.romanov@gmail.com         nxt_string("unit_jars"),
289977Smax.romanov@gmail.com         NXT_CONF_MAP_CSTRZ,
290977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.unit_jars),
291977Smax.romanov@gmail.com     },
2921684Smax.romanov@nginx.com     {
2931684Smax.romanov@nginx.com         nxt_string("threads"),
2941684Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
2951684Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.java.threads),
2961684Smax.romanov@nginx.com     },
2971684Smax.romanov@nginx.com     {
2981684Smax.romanov@nginx.com         nxt_string("thread_stack_size"),
2991684Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
3001684Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.java.thread_stack_size),
3011684Smax.romanov@nginx.com     },
302977Smax.romanov@gmail.com 
303977Smax.romanov@gmail.com };
304977Smax.romanov@gmail.com 
305977Smax.romanov@gmail.com 
306546Smax.romanov@nginx.com static nxt_conf_app_map_t  nxt_app_maps[] = {
307804Svbart@nginx.com     { nxt_nitems(nxt_external_app_conf),  nxt_external_app_conf },
308804Svbart@nginx.com     { nxt_nitems(nxt_python_app_conf),    nxt_python_app_conf },
309804Svbart@nginx.com     { nxt_nitems(nxt_php_app_conf),       nxt_php_app_conf },
310804Svbart@nginx.com     { nxt_nitems(nxt_perl_app_conf),      nxt_perl_app_conf },
311804Svbart@nginx.com     { nxt_nitems(nxt_ruby_app_conf),      nxt_ruby_app_conf },
312977Smax.romanov@gmail.com     { nxt_nitems(nxt_java_app_conf),      nxt_java_app_conf },
313510Salexander.borisov@nginx.com };
314510Salexander.borisov@nginx.com 
315510Salexander.borisov@nginx.com 
316240Sigor@sysoev.ru static void
317240Sigor@sysoev.ru nxt_port_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
318240Sigor@sysoev.ru {
319240Sigor@sysoev.ru     nxt_debug(task, "main data: %*s",
320240Sigor@sysoev.ru               nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos);
321240Sigor@sysoev.ru }
322240Sigor@sysoev.ru 
323240Sigor@sysoev.ru 
324240Sigor@sysoev.ru static void
3251488St.nateldemoura@f5.com nxt_port_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
326240Sigor@sysoev.ru {
3271488St.nateldemoura@f5.com     u_char                 *start, *p, ch;
328536Svbart@nginx.com     size_t                 type_len;
329536Svbart@nginx.com     nxt_int_t              ret;
330240Sigor@sysoev.ru     nxt_buf_t              *b;
331318Smax.romanov@nginx.com     nxt_port_t             *port;
3321182St.nateldemoura@f5.com     nxt_runtime_t          *rt;
3331488St.nateldemoura@f5.com     nxt_process_t          *process;
334536Svbart@nginx.com     nxt_app_type_t         idx;
335240Sigor@sysoev.ru     nxt_conf_value_t       *conf;
3361488St.nateldemoura@f5.com     nxt_process_init_t     *init;
3371488St.nateldemoura@f5.com     nxt_common_app_conf_t  *app_conf;
338240Sigor@sysoev.ru 
339318Smax.romanov@nginx.com     ret = NXT_ERROR;
340318Smax.romanov@nginx.com 
3411488St.nateldemoura@f5.com     rt = task->thread->runtime;
342352Smax.romanov@nginx.com 
3431488St.nateldemoura@f5.com     process = nxt_main_process_new(task, rt);
3441488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
345352Smax.romanov@nginx.com         return;
346352Smax.romanov@nginx.com     }
347352Smax.romanov@nginx.com 
3481488St.nateldemoura@f5.com     init = nxt_process_init(process);
3491488St.nateldemoura@f5.com 
3501488St.nateldemoura@f5.com     *init = nxt_app_process;
351352Smax.romanov@nginx.com 
3521488St.nateldemoura@f5.com     b = nxt_buf_chk_make_plain(process->mem_pool, msg->buf, msg->size);
353352Smax.romanov@nginx.com     if (b == NULL) {
3541488St.nateldemoura@f5.com         goto failed;
355352Smax.romanov@nginx.com     }
356240Sigor@sysoev.ru 
3571488St.nateldemoura@f5.com     nxt_debug(task, "main start process: %*s", b->mem.free - b->mem.pos,
358240Sigor@sysoev.ru               b->mem.pos);
359240Sigor@sysoev.ru 
3601488St.nateldemoura@f5.com     app_conf = nxt_mp_zalloc(process->mem_pool, sizeof(nxt_common_app_conf_t));
3611488St.nateldemoura@f5.com     if (nxt_slow_path(app_conf == NULL)) {
3621488St.nateldemoura@f5.com         goto failed;
3631488St.nateldemoura@f5.com     }
364240Sigor@sysoev.ru 
365240Sigor@sysoev.ru     start = b->mem.pos;
366240Sigor@sysoev.ru 
3671488St.nateldemoura@f5.com     app_conf->name.start = start;
3681488St.nateldemoura@f5.com     app_conf->name.length = nxt_strlen(start);
3691488St.nateldemoura@f5.com 
3701488St.nateldemoura@f5.com     init->name = (const char *) start;
3711488St.nateldemoura@f5.com 
3721488St.nateldemoura@f5.com     process->name = nxt_mp_alloc(process->mem_pool, app_conf->name.length
3731488St.nateldemoura@f5.com                                  + sizeof("\"\" application") + 1);
3741488St.nateldemoura@f5.com 
3751488St.nateldemoura@f5.com     if (nxt_slow_path(process->name == NULL)) {
3761488St.nateldemoura@f5.com         goto failed;
3771488St.nateldemoura@f5.com     }
378240Sigor@sysoev.ru 
3791488St.nateldemoura@f5.com     p = (u_char *) process->name;
3801488St.nateldemoura@f5.com     *p++ = '"';
3811488St.nateldemoura@f5.com     p = nxt_cpymem(p, init->name, app_conf->name.length);
3821488St.nateldemoura@f5.com     p = nxt_cpymem(p, "\" application", 13);
3831488St.nateldemoura@f5.com     *p = '\0';
384240Sigor@sysoev.ru 
3851488St.nateldemoura@f5.com     app_conf->shm_limit = 100 * 1024 * 1024;
386240Sigor@sysoev.ru 
3871488St.nateldemoura@f5.com     start += app_conf->name.length + 1;
3881488St.nateldemoura@f5.com 
3891488St.nateldemoura@f5.com     conf = nxt_conf_json_parse(process->mem_pool, start, b->mem.free, NULL);
390240Sigor@sysoev.ru     if (conf == NULL) {
391564Svbart@nginx.com         nxt_alert(task, "router app configuration parsing error");
392318Smax.romanov@nginx.com 
393318Smax.romanov@nginx.com         goto failed;
394240Sigor@sysoev.ru     }
395240Sigor@sysoev.ru 
3961182St.nateldemoura@f5.com     rt = task->thread->runtime;
3971182St.nateldemoura@f5.com 
3981488St.nateldemoura@f5.com     app_conf->user.start  = (u_char*)rt->user_cred.user;
3991488St.nateldemoura@f5.com     app_conf->user.length = nxt_strlen(rt->user_cred.user);
400240Sigor@sysoev.ru 
4011488St.nateldemoura@f5.com     ret = nxt_conf_map_object(process->mem_pool, conf, nxt_common_app_conf,
4021488St.nateldemoura@f5.com                               nxt_nitems(nxt_common_app_conf), app_conf);
4031488St.nateldemoura@f5.com 
404240Sigor@sysoev.ru     if (ret != NXT_OK) {
405564Svbart@nginx.com         nxt_alert(task, "failed to map common app conf received from router");
406318Smax.romanov@nginx.com         goto failed;
407240Sigor@sysoev.ru     }
408240Sigor@sysoev.ru 
4091488St.nateldemoura@f5.com     for (type_len = 0; type_len != app_conf->type.length; type_len++) {
4101488St.nateldemoura@f5.com         ch = app_conf->type.start[type_len];
411536Svbart@nginx.com 
412536Svbart@nginx.com         if (ch == ' ' || nxt_isdigit(ch)) {
413536Svbart@nginx.com             break;
414536Svbart@nginx.com         }
415536Svbart@nginx.com     }
416536Svbart@nginx.com 
4171488St.nateldemoura@f5.com     idx = nxt_app_parse_type(app_conf->type.start, type_len);
418510Salexander.borisov@nginx.com 
419546Smax.romanov@nginx.com     if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) {
420564Svbart@nginx.com         nxt_alert(task, "invalid app type %d received from router", (int) idx);
421546Smax.romanov@nginx.com         goto failed;
422546Smax.romanov@nginx.com     }
423510Salexander.borisov@nginx.com 
4241488St.nateldemoura@f5.com     ret = nxt_conf_map_object(process->mem_pool, conf, nxt_app_maps[idx].map,
4251488St.nateldemoura@f5.com                               nxt_app_maps[idx].size, app_conf);
426510Salexander.borisov@nginx.com 
427546Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
428564Svbart@nginx.com         nxt_alert(task, "failed to map app conf received from router");
429546Smax.romanov@nginx.com         goto failed;
430546Smax.romanov@nginx.com     }
431510Salexander.borisov@nginx.com 
4321488St.nateldemoura@f5.com     if (app_conf->limits != NULL) {
4331488St.nateldemoura@f5.com         ret = nxt_conf_map_object(process->mem_pool, app_conf->limits,
4341320Smax.romanov@nginx.com                                   nxt_common_app_limits_conf,
4351320Smax.romanov@nginx.com                                   nxt_nitems(nxt_common_app_limits_conf),
4361488St.nateldemoura@f5.com                                   app_conf);
4371320Smax.romanov@nginx.com 
4381320Smax.romanov@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
4391320Smax.romanov@nginx.com             nxt_alert(task, "failed to map app limits received from router");
4401320Smax.romanov@nginx.com             goto failed;
4411320Smax.romanov@nginx.com         }
4421320Smax.romanov@nginx.com     }
4431320Smax.romanov@nginx.com 
4441488St.nateldemoura@f5.com     app_conf->self = conf;
4451488St.nateldemoura@f5.com 
4461488St.nateldemoura@f5.com     process->stream = msg->port_msg.stream;
4471488St.nateldemoura@f5.com     process->data.app = app_conf;
4481473Svbart@nginx.com 
4491488St.nateldemoura@f5.com     ret = nxt_main_start_process(task, process);
4501488St.nateldemoura@f5.com     if (nxt_fast_path(ret == NXT_OK || ret == NXT_AGAIN)) {
4511488St.nateldemoura@f5.com         return;
4521488St.nateldemoura@f5.com     }
453240Sigor@sysoev.ru 
454318Smax.romanov@nginx.com failed:
455318Smax.romanov@nginx.com 
4561488St.nateldemoura@f5.com     nxt_process_use(task, process, -1);
4571488St.nateldemoura@f5.com 
4581488St.nateldemoura@f5.com     port = nxt_runtime_port_find(rt, msg->port_msg.pid,
4591488St.nateldemoura@f5.com                                  msg->port_msg.reply_port);
4601488St.nateldemoura@f5.com 
4611488St.nateldemoura@f5.com     if (nxt_fast_path(port != NULL)) {
4621488St.nateldemoura@f5.com         nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
4631488St.nateldemoura@f5.com                               -1, msg->port_msg.stream, 0, NULL);
4641488St.nateldemoura@f5.com     }
4651488St.nateldemoura@f5.com }
4661488St.nateldemoura@f5.com 
4671488St.nateldemoura@f5.com 
4681488St.nateldemoura@f5.com static void
4691488St.nateldemoura@f5.com nxt_main_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
4701488St.nateldemoura@f5.com {
4711488St.nateldemoura@f5.com     nxt_port_t     *port;
4721488St.nateldemoura@f5.com     nxt_process_t  *process;
4731488St.nateldemoura@f5.com     nxt_runtime_t  *rt;
4741488St.nateldemoura@f5.com 
4751488St.nateldemoura@f5.com     rt = task->thread->runtime;
4761488St.nateldemoura@f5.com 
4771488St.nateldemoura@f5.com     process = nxt_runtime_process_find(rt, msg->port_msg.pid);
4781488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
4791488St.nateldemoura@f5.com         return;
480318Smax.romanov@nginx.com     }
481318Smax.romanov@nginx.com 
4821488St.nateldemoura@f5.com     nxt_assert(process->state == NXT_PROCESS_STATE_CREATING);
4831488St.nateldemoura@f5.com 
4841488St.nateldemoura@f5.com     port = nxt_runtime_port_find(rt, msg->port_msg.pid,
4851488St.nateldemoura@f5.com                                  msg->port_msg.reply_port);
4861488St.nateldemoura@f5.com 
4871488St.nateldemoura@f5.com 
4881488St.nateldemoura@f5.com     if (nxt_slow_path(port == NULL)) {
4891488St.nateldemoura@f5.com         return;
4901488St.nateldemoura@f5.com     }
4911488St.nateldemoura@f5.com 
4921488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER)
4931488St.nateldemoura@f5.com     if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
4941488St.nateldemoura@f5.com         if (nxt_slow_path(nxt_clone_credential_map(task, process->pid,
4951488St.nateldemoura@f5.com                                                    process->user_cred,
4961488St.nateldemoura@f5.com                                                    &process->isolation.clone)
4971488St.nateldemoura@f5.com                           != NXT_OK))
4981488St.nateldemoura@f5.com         {
4991488St.nateldemoura@f5.com             (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
5001488St.nateldemoura@f5.com                                          -1, msg->port_msg.stream, 0, NULL);
5011488St.nateldemoura@f5.com             return;
5021488St.nateldemoura@f5.com         }
5031488St.nateldemoura@f5.com      }
5041488St.nateldemoura@f5.com 
5051488St.nateldemoura@f5.com #endif
5061488St.nateldemoura@f5.com 
5071488St.nateldemoura@f5.com     process->state = NXT_PROCESS_STATE_CREATED;
5081488St.nateldemoura@f5.com 
5091488St.nateldemoura@f5.com     (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST,
5101488St.nateldemoura@f5.com                                  -1, msg->port_msg.stream, 0, NULL);
511240Sigor@sysoev.ru }
512240Sigor@sysoev.ru 
513240Sigor@sysoev.ru 
514320Smax.romanov@nginx.com static nxt_port_handlers_t  nxt_main_process_port_handlers = {
5151488St.nateldemoura@f5.com     .data             = nxt_port_main_data_handler,
5161488St.nateldemoura@f5.com     .process_created  = nxt_main_process_created_handler,
5171488St.nateldemoura@f5.com     .process_ready    = nxt_port_process_ready_handler,
5181488St.nateldemoura@f5.com     .start_process    = nxt_port_main_start_process_handler,
5191488St.nateldemoura@f5.com     .socket           = nxt_main_port_socket_handler,
5201488St.nateldemoura@f5.com     .modules          = nxt_main_port_modules_handler,
5211488St.nateldemoura@f5.com     .conf_store       = nxt_main_port_conf_store_handler,
522774Svbart@nginx.com #if (NXT_TLS)
5231488St.nateldemoura@f5.com     .cert_get         = nxt_cert_store_get_handler,
5241488St.nateldemoura@f5.com     .cert_delete      = nxt_cert_store_delete_handler,
525774Svbart@nginx.com #endif
5261488St.nateldemoura@f5.com     .access_log       = nxt_main_port_access_log_handler,
5271488St.nateldemoura@f5.com     .rpc_ready        = nxt_port_rpc_handler,
5281488St.nateldemoura@f5.com     .rpc_error        = nxt_port_rpc_handler,
529240Sigor@sysoev.ru };
530240Sigor@sysoev.ru 
531240Sigor@sysoev.ru 
532240Sigor@sysoev.ru static nxt_int_t
533240Sigor@sysoev.ru nxt_main_process_port_create(nxt_task_t *task, nxt_runtime_t *rt)
534240Sigor@sysoev.ru {
535240Sigor@sysoev.ru     nxt_int_t      ret;
536240Sigor@sysoev.ru     nxt_port_t     *port;
537240Sigor@sysoev.ru     nxt_process_t  *process;
538240Sigor@sysoev.ru 
5391254Shongzhidao@gmail.com     port = nxt_runtime_process_port_create(task, rt, nxt_pid, 0,
5401254Shongzhidao@gmail.com                                            NXT_PROCESS_MAIN);
541240Sigor@sysoev.ru     if (nxt_slow_path(port == NULL)) {
542240Sigor@sysoev.ru         return NXT_ERROR;
543240Sigor@sysoev.ru     }
544240Sigor@sysoev.ru 
5451254Shongzhidao@gmail.com     process = port->process;
546349Smax.romanov@nginx.com 
547240Sigor@sysoev.ru     ret = nxt_port_socket_init(task, port, 0);
548240Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
5491488St.nateldemoura@f5.com         nxt_port_use(task, port, -1);
550240Sigor@sysoev.ru         return ret;
551240Sigor@sysoev.ru     }
552240Sigor@sysoev.ru 
553240Sigor@sysoev.ru     /*
554240Sigor@sysoev.ru      * A main process port.  A write port is not closed
5551488St.nateldemoura@f5.com      * since it should be inherited by processes.
556240Sigor@sysoev.ru      */
557320Smax.romanov@nginx.com     nxt_port_enable(task, port, &nxt_main_process_port_handlers);
558240Sigor@sysoev.ru 
5591488St.nateldemoura@f5.com     process->state = NXT_PROCESS_STATE_READY;
560240Sigor@sysoev.ru 
561240Sigor@sysoev.ru     return NXT_OK;
562240Sigor@sysoev.ru }
563240Sigor@sysoev.ru 
564240Sigor@sysoev.ru 
565240Sigor@sysoev.ru static void
566240Sigor@sysoev.ru nxt_main_process_title(nxt_task_t *task)
567240Sigor@sysoev.ru {
568240Sigor@sysoev.ru     u_char      *p, *end;
569240Sigor@sysoev.ru     nxt_uint_t  i;
570240Sigor@sysoev.ru     u_char      title[2048];
571240Sigor@sysoev.ru 
572240Sigor@sysoev.ru     end = title + sizeof(title) - 1;
573240Sigor@sysoev.ru 
574680Sigor@sysoev.ru     p = nxt_sprintf(title, end, "unit: main v" NXT_VERSION " [%s",
575680Sigor@sysoev.ru                     nxt_process_argv[0]);
576240Sigor@sysoev.ru 
577240Sigor@sysoev.ru     for (i = 1; nxt_process_argv[i] != NULL; i++) {
578240Sigor@sysoev.ru         p = nxt_sprintf(p, end, " %s", nxt_process_argv[i]);
579240Sigor@sysoev.ru     }
580240Sigor@sysoev.ru 
581240Sigor@sysoev.ru     if (p < end) {
582240Sigor@sysoev.ru         *p++ = ']';
583240Sigor@sysoev.ru     }
584240Sigor@sysoev.ru 
585240Sigor@sysoev.ru     *p = '\0';
586240Sigor@sysoev.ru 
587240Sigor@sysoev.ru     nxt_process_title(task, "%s", title);
588240Sigor@sysoev.ru }
589240Sigor@sysoev.ru 
590240Sigor@sysoev.ru 
591240Sigor@sysoev.ru static nxt_int_t
5921488St.nateldemoura@f5.com nxt_main_process_create(nxt_task_t *task, const nxt_process_init_t init)
593240Sigor@sysoev.ru {
5941488St.nateldemoura@f5.com     nxt_int_t           ret;
5951488St.nateldemoura@f5.com     nxt_runtime_t       *rt;
5961488St.nateldemoura@f5.com     nxt_process_t       *process;
5971488St.nateldemoura@f5.com     nxt_process_init_t  *pinit;
598240Sigor@sysoev.ru 
5991488St.nateldemoura@f5.com     rt = task->thread->runtime;
6001302St.nateldemoura@f5.com 
6011488St.nateldemoura@f5.com     process = nxt_main_process_new(task, rt);
6021488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
603368Svbart@nginx.com         return NXT_ERROR;
604368Svbart@nginx.com     }
605368Svbart@nginx.com 
6061488St.nateldemoura@f5.com     process->name = init.name;
6071488St.nateldemoura@f5.com     process->user_cred = &rt->user_cred;
608314Svbart@nginx.com 
6091488St.nateldemoura@f5.com     pinit = nxt_process_init(process);
6101488St.nateldemoura@f5.com     *pinit = init;
611314Svbart@nginx.com 
6121488St.nateldemoura@f5.com     ret = nxt_main_start_process(task, process);
6131488St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
6141488St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
615314Svbart@nginx.com     }
616314Svbart@nginx.com 
617314Svbart@nginx.com     return ret;
618240Sigor@sysoev.ru }
619240Sigor@sysoev.ru 
620240Sigor@sysoev.ru 
6211488St.nateldemoura@f5.com static nxt_process_t *
6221488St.nateldemoura@f5.com nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt)
623240Sigor@sysoev.ru {
6241488St.nateldemoura@f5.com     nxt_process_t  *process;
625240Sigor@sysoev.ru 
6261488St.nateldemoura@f5.com     process = nxt_runtime_process_new(rt);
6271488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
6281488St.nateldemoura@f5.com         return NULL;
629240Sigor@sysoev.ru     }
630240Sigor@sysoev.ru 
6311488St.nateldemoura@f5.com     process->mem_pool = nxt_mp_create(1024, 128, 256, 32);
6321488St.nateldemoura@f5.com     if (process->mem_pool == NULL) {
6331488St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6341488St.nateldemoura@f5.com         return NULL;
635240Sigor@sysoev.ru     }
636240Sigor@sysoev.ru 
6371488St.nateldemoura@f5.com     return process;
638240Sigor@sysoev.ru }
639240Sigor@sysoev.ru 
6401302St.nateldemoura@f5.com 
641240Sigor@sysoev.ru static nxt_int_t
6421488St.nateldemoura@f5.com nxt_main_start_process(nxt_task_t *task, nxt_process_t *process)
643240Sigor@sysoev.ru {
6441488St.nateldemoura@f5.com     nxt_mp_t            *tmp_mp;
6451182St.nateldemoura@f5.com     nxt_int_t           ret;
6461488St.nateldemoura@f5.com     nxt_pid_t           pid;
6471488St.nateldemoura@f5.com     nxt_port_t          *port;
648240Sigor@sysoev.ru     nxt_process_init_t  *init;
649240Sigor@sysoev.ru 
6501488St.nateldemoura@f5.com     init = nxt_process_init(process);
651240Sigor@sysoev.ru 
652240Sigor@sysoev.ru     port = nxt_port_new(task, 0, 0, init->type);
653240Sigor@sysoev.ru     if (nxt_slow_path(port == NULL)) {
654240Sigor@sysoev.ru         return NXT_ERROR;
655240Sigor@sysoev.ru     }
656240Sigor@sysoev.ru 
657240Sigor@sysoev.ru     nxt_process_port_add(task, process, port);
658240Sigor@sysoev.ru 
659240Sigor@sysoev.ru     ret = nxt_port_socket_init(task, port, 0);
660240Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
6611565St.nateldemoura@f5.com         goto free_port;
6621488St.nateldemoura@f5.com     }
6631488St.nateldemoura@f5.com 
6641488St.nateldemoura@f5.com     tmp_mp = nxt_mp_create(1024, 128, 256, 32);
6651565St.nateldemoura@f5.com     if (nxt_slow_path(tmp_mp == NULL)) {
6661565St.nateldemoura@f5.com         ret = NXT_ERROR;
6671565St.nateldemoura@f5.com 
6681565St.nateldemoura@f5.com         goto close_port;
6691488St.nateldemoura@f5.com     }
6701488St.nateldemoura@f5.com 
6711488St.nateldemoura@f5.com     if (init->prefork) {
6721488St.nateldemoura@f5.com         ret = init->prefork(task, process, tmp_mp);
6731488St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
6741565St.nateldemoura@f5.com             goto free_mempool;
6751488St.nateldemoura@f5.com         }
676240Sigor@sysoev.ru     }
677240Sigor@sysoev.ru 
678240Sigor@sysoev.ru     pid = nxt_process_create(task, process);
679240Sigor@sysoev.ru 
680240Sigor@sysoev.ru     switch (pid) {
681240Sigor@sysoev.ru 
682240Sigor@sysoev.ru     case -1:
6831565St.nateldemoura@f5.com         ret = NXT_ERROR;
6841488St.nateldemoura@f5.com         break;
685240Sigor@sysoev.ru 
686240Sigor@sysoev.ru     case 0:
6871488St.nateldemoura@f5.com         /* The child process: return to the event engine work queue loop. */
6881180Smax.romanov@nginx.com 
6891565St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6901565St.nateldemoura@f5.com 
6911488St.nateldemoura@f5.com         ret = NXT_AGAIN;
6921488St.nateldemoura@f5.com         break;
693240Sigor@sysoev.ru 
694240Sigor@sysoev.ru     default:
695240Sigor@sysoev.ru         /* The main process created a new process. */
696240Sigor@sysoev.ru 
6971565St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6981565St.nateldemoura@f5.com 
699240Sigor@sysoev.ru         nxt_port_read_close(port);
700240Sigor@sysoev.ru         nxt_port_write_enable(task, port);
701240Sigor@sysoev.ru 
7021488St.nateldemoura@f5.com         ret = NXT_OK;
7031488St.nateldemoura@f5.com         break;
704240Sigor@sysoev.ru     }
705240Sigor@sysoev.ru 
7061565St.nateldemoura@f5.com free_mempool:
7071565St.nateldemoura@f5.com 
7081565St.nateldemoura@f5.com     nxt_mp_destroy(tmp_mp);
7091565St.nateldemoura@f5.com 
7101565St.nateldemoura@f5.com close_port:
7111565St.nateldemoura@f5.com 
7121565St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
7131565St.nateldemoura@f5.com         nxt_port_close(task, port);
7141565St.nateldemoura@f5.com     }
7151565St.nateldemoura@f5.com 
7161565St.nateldemoura@f5.com free_port:
717240Sigor@sysoev.ru 
7181488St.nateldemoura@f5.com     nxt_port_use(task, port, -1);
719240Sigor@sysoev.ru 
7201488St.nateldemoura@f5.com     return ret;
721240Sigor@sysoev.ru }
722240Sigor@sysoev.ru 
723240Sigor@sysoev.ru 
724240Sigor@sysoev.ru static void
725240Sigor@sysoev.ru nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, void *data)
726240Sigor@sysoev.ru {
727240Sigor@sysoev.ru     nxt_debug(task, "sigterm handler signo:%d (%s)",
728240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
729240Sigor@sysoev.ru 
730240Sigor@sysoev.ru     /* TODO: fast exit. */
731240Sigor@sysoev.ru 
732240Sigor@sysoev.ru     nxt_exiting = 1;
733240Sigor@sysoev.ru 
734697Sigor@sysoev.ru     nxt_runtime_quit(task, 0);
735240Sigor@sysoev.ru }
736240Sigor@sysoev.ru 
737240Sigor@sysoev.ru 
738240Sigor@sysoev.ru static void
739240Sigor@sysoev.ru nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, void *data)
740240Sigor@sysoev.ru {
741240Sigor@sysoev.ru     nxt_debug(task, "sigquit handler signo:%d (%s)",
742240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
743240Sigor@sysoev.ru 
744240Sigor@sysoev.ru     /* TODO: graceful exit. */
745240Sigor@sysoev.ru 
746240Sigor@sysoev.ru     nxt_exiting = 1;
747240Sigor@sysoev.ru 
748697Sigor@sysoev.ru     nxt_runtime_quit(task, 0);
749240Sigor@sysoev.ru }
750240Sigor@sysoev.ru 
751240Sigor@sysoev.ru 
752240Sigor@sysoev.ru static void
753240Sigor@sysoev.ru nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, void *data)
754240Sigor@sysoev.ru {
755240Sigor@sysoev.ru     nxt_mp_t        *mp;
756240Sigor@sysoev.ru     nxt_int_t       ret;
757240Sigor@sysoev.ru     nxt_uint_t      n;
758631Svbart@nginx.com     nxt_port_t      *port;
759240Sigor@sysoev.ru     nxt_file_t      *file, *new_file;
760631Svbart@nginx.com     nxt_array_t     *new_files;
761240Sigor@sysoev.ru     nxt_runtime_t   *rt;
762240Sigor@sysoev.ru 
763240Sigor@sysoev.ru     nxt_log(task, NXT_LOG_NOTICE, "signal %d (%s) recevied, %s",
764240Sigor@sysoev.ru             (int) (uintptr_t) obj, data, "log files rotation");
765240Sigor@sysoev.ru 
766631Svbart@nginx.com     rt = task->thread->runtime;
767631Svbart@nginx.com 
768631Svbart@nginx.com     port = rt->port_by_type[NXT_PROCESS_ROUTER];
769631Svbart@nginx.com 
770631Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
771631Svbart@nginx.com         (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_ACCESS_LOG,
772631Svbart@nginx.com                                      -1, 0, 0, NULL);
773631Svbart@nginx.com     }
774631Svbart@nginx.com 
775240Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
776240Sigor@sysoev.ru     if (mp == NULL) {
777240Sigor@sysoev.ru         return;
778240Sigor@sysoev.ru     }
779240Sigor@sysoev.ru 
780240Sigor@sysoev.ru     n = nxt_list_nelts(rt->log_files);
781240Sigor@sysoev.ru 
782240Sigor@sysoev.ru     new_files = nxt_array_create(mp, n, sizeof(nxt_file_t));
783240Sigor@sysoev.ru     if (new_files == NULL) {
784240Sigor@sysoev.ru         nxt_mp_destroy(mp);
785240Sigor@sysoev.ru         return;
786240Sigor@sysoev.ru     }
787240Sigor@sysoev.ru 
788240Sigor@sysoev.ru     nxt_list_each(file, rt->log_files) {
789240Sigor@sysoev.ru 
790240Sigor@sysoev.ru         /* This allocation cannot fail. */
791240Sigor@sysoev.ru         new_file = nxt_array_add(new_files);
792240Sigor@sysoev.ru 
793240Sigor@sysoev.ru         new_file->name = file->name;
794240Sigor@sysoev.ru         new_file->fd = NXT_FILE_INVALID;
795564Svbart@nginx.com         new_file->log_level = NXT_LOG_ALERT;
796240Sigor@sysoev.ru 
797240Sigor@sysoev.ru         ret = nxt_file_open(task, new_file, O_WRONLY | O_APPEND, O_CREAT,
798240Sigor@sysoev.ru                             NXT_FILE_OWNER_ACCESS);
799240Sigor@sysoev.ru 
800240Sigor@sysoev.ru         if (ret != NXT_OK) {
801240Sigor@sysoev.ru             goto fail;
802240Sigor@sysoev.ru         }
803240Sigor@sysoev.ru 
804240Sigor@sysoev.ru     } nxt_list_loop;
805240Sigor@sysoev.ru 
806240Sigor@sysoev.ru     new_file = new_files->elts;
807240Sigor@sysoev.ru 
808240Sigor@sysoev.ru     ret = nxt_file_stderr(&new_file[0]);
809240Sigor@sysoev.ru 
810240Sigor@sysoev.ru     if (ret == NXT_OK) {
811240Sigor@sysoev.ru         n = 0;
812240Sigor@sysoev.ru 
813240Sigor@sysoev.ru         nxt_list_each(file, rt->log_files) {
814240Sigor@sysoev.ru 
815240Sigor@sysoev.ru             nxt_port_change_log_file(task, rt, n, new_file[n].fd);
816240Sigor@sysoev.ru             /*
817240Sigor@sysoev.ru              * The old log file descriptor must be closed at the moment
818240Sigor@sysoev.ru              * when no other threads use it.  dup2() allows to use the
819240Sigor@sysoev.ru              * old file descriptor for new log file.  This change is
820240Sigor@sysoev.ru              * performed atomically in the kernel.
821240Sigor@sysoev.ru              */
822240Sigor@sysoev.ru             (void) nxt_file_redirect(file, new_file[n].fd);
823240Sigor@sysoev.ru 
824240Sigor@sysoev.ru             n++;
825240Sigor@sysoev.ru 
826240Sigor@sysoev.ru         } nxt_list_loop;
827240Sigor@sysoev.ru 
828240Sigor@sysoev.ru         nxt_mp_destroy(mp);
829240Sigor@sysoev.ru         return;
8301008Szelenkov@nginx.com     }
831240Sigor@sysoev.ru 
832240Sigor@sysoev.ru fail:
833240Sigor@sysoev.ru 
834240Sigor@sysoev.ru     new_file = new_files->elts;
835240Sigor@sysoev.ru     n = new_files->nelts;
836240Sigor@sysoev.ru 
837240Sigor@sysoev.ru     while (n != 0) {
838240Sigor@sysoev.ru         if (new_file->fd != NXT_FILE_INVALID) {
839240Sigor@sysoev.ru             nxt_file_close(task, new_file);
840240Sigor@sysoev.ru         }
841240Sigor@sysoev.ru 
842240Sigor@sysoev.ru         new_file++;
843240Sigor@sysoev.ru         n--;
844240Sigor@sysoev.ru     }
845240Sigor@sysoev.ru 
846240Sigor@sysoev.ru     nxt_mp_destroy(mp);
847240Sigor@sysoev.ru }
848240Sigor@sysoev.ru 
849240Sigor@sysoev.ru 
850240Sigor@sysoev.ru static void
851240Sigor@sysoev.ru nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, void *data)
852240Sigor@sysoev.ru {
853240Sigor@sysoev.ru     int                    status;
854240Sigor@sysoev.ru     nxt_err_t              err;
855240Sigor@sysoev.ru     nxt_pid_t              pid;
856240Sigor@sysoev.ru 
857240Sigor@sysoev.ru     nxt_debug(task, "sigchld handler signo:%d (%s)",
858240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
859240Sigor@sysoev.ru 
860240Sigor@sysoev.ru     for ( ;; ) {
861240Sigor@sysoev.ru         pid = waitpid(-1, &status, WNOHANG);
862240Sigor@sysoev.ru 
863240Sigor@sysoev.ru         if (pid == -1) {
864240Sigor@sysoev.ru 
865240Sigor@sysoev.ru             switch (err = nxt_errno) {
866240Sigor@sysoev.ru 
867240Sigor@sysoev.ru             case NXT_ECHILD:
868240Sigor@sysoev.ru                 return;
869240Sigor@sysoev.ru 
870240Sigor@sysoev.ru             case NXT_EINTR:
871240Sigor@sysoev.ru                 continue;
872240Sigor@sysoev.ru 
873240Sigor@sysoev.ru             default:
874564Svbart@nginx.com                 nxt_alert(task, "waitpid() failed: %E", err);
875240Sigor@sysoev.ru                 return;
876240Sigor@sysoev.ru             }
877240Sigor@sysoev.ru         }
878240Sigor@sysoev.ru 
879240Sigor@sysoev.ru         nxt_debug(task, "waitpid(): %PI", pid);
880240Sigor@sysoev.ru 
881240Sigor@sysoev.ru         if (pid == 0) {
882240Sigor@sysoev.ru             return;
883240Sigor@sysoev.ru         }
884240Sigor@sysoev.ru 
885240Sigor@sysoev.ru         if (WTERMSIG(status)) {
886240Sigor@sysoev.ru #ifdef WCOREDUMP
887564Svbart@nginx.com             nxt_alert(task, "process %PI exited on signal %d%s",
888564Svbart@nginx.com                       pid, WTERMSIG(status),
889564Svbart@nginx.com                       WCOREDUMP(status) ? " (core dumped)" : "");
890240Sigor@sysoev.ru #else
891564Svbart@nginx.com             nxt_alert(task, "process %PI exited on signal %d",
892564Svbart@nginx.com                       pid, WTERMSIG(status));
893240Sigor@sysoev.ru #endif
894240Sigor@sysoev.ru 
895240Sigor@sysoev.ru         } else {
896240Sigor@sysoev.ru             nxt_trace(task, "process %PI exited with code %d",
897240Sigor@sysoev.ru                       pid, WEXITSTATUS(status));
898240Sigor@sysoev.ru         }
899240Sigor@sysoev.ru 
9001488St.nateldemoura@f5.com         nxt_main_cleanup_process(task, pid);
901240Sigor@sysoev.ru     }
902240Sigor@sysoev.ru }
903240Sigor@sysoev.ru 
904240Sigor@sysoev.ru 
905240Sigor@sysoev.ru static void
906944Sigor@sysoev.ru nxt_main_process_signal_handler(nxt_task_t *task, void *obj, void *data)
907944Sigor@sysoev.ru {
908944Sigor@sysoev.ru     nxt_trace(task, "signal signo:%d (%s) recevied, ignored",
909944Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
910944Sigor@sysoev.ru }
911944Sigor@sysoev.ru 
912944Sigor@sysoev.ru 
913944Sigor@sysoev.ru static void
9141488St.nateldemoura@f5.com nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid)
915240Sigor@sysoev.ru {
9161488St.nateldemoura@f5.com     int                 stream;
9171488St.nateldemoura@f5.com     nxt_int_t           ret;
9181488St.nateldemoura@f5.com     nxt_buf_t           *buf;
9191488St.nateldemoura@f5.com     nxt_port_t          *port;
9201488St.nateldemoura@f5.com     const char          *name;
9211488St.nateldemoura@f5.com     nxt_runtime_t       *rt;
9221488St.nateldemoura@f5.com     nxt_process_t       *process;
9231488St.nateldemoura@f5.com     nxt_process_init_t  init;
924240Sigor@sysoev.ru 
925240Sigor@sysoev.ru     rt = task->thread->runtime;
926240Sigor@sysoev.ru 
927240Sigor@sysoev.ru     process = nxt_runtime_process_find(rt, pid);
9281488St.nateldemoura@f5.com     if (!process) {
9291488St.nateldemoura@f5.com         return;
9301488St.nateldemoura@f5.com     }
931240Sigor@sysoev.ru 
9321579St.nateldemoura@f5.com     if (process->isolation.cleanup != NULL) {
9331579St.nateldemoura@f5.com         process->isolation.cleanup(task, process);
9341489St.nateldemoura@f5.com     }
9351489St.nateldemoura@f5.com 
9361488St.nateldemoura@f5.com     name = process->name;
9371488St.nateldemoura@f5.com     stream = process->stream;
9381488St.nateldemoura@f5.com     init = *((nxt_process_init_t *) nxt_process_init(process));
939366Smax.romanov@nginx.com 
9401488St.nateldemoura@f5.com     if (process->state == NXT_PROCESS_STATE_READY) {
9411488St.nateldemoura@f5.com         process->stream = 0;
9421488St.nateldemoura@f5.com     }
943240Sigor@sysoev.ru 
9441488St.nateldemoura@f5.com     nxt_process_close_ports(task, process);
9451302St.nateldemoura@f5.com 
9461488St.nateldemoura@f5.com     if (nxt_exiting) {
9471488St.nateldemoura@f5.com         if (rt->nprocesses <= 1) {
9481488St.nateldemoura@f5.com             nxt_runtime_quit(task, 0);
9491211Smax.romanov@nginx.com         }
9501211Smax.romanov@nginx.com 
9511488St.nateldemoura@f5.com         return;
952240Sigor@sysoev.ru     }
953754Smax.romanov@nginx.com 
954754Smax.romanov@nginx.com     nxt_runtime_process_each(rt, process) {
955754Smax.romanov@nginx.com 
9561488St.nateldemoura@f5.com         if (process->pid == nxt_pid
9571488St.nateldemoura@f5.com             || process->pid == pid
9581488St.nateldemoura@f5.com             || nxt_queue_is_empty(&process->ports))
9591488St.nateldemoura@f5.com         {
9601488St.nateldemoura@f5.com             continue;
9611488St.nateldemoura@f5.com         }
9621488St.nateldemoura@f5.com 
9631488St.nateldemoura@f5.com         port = nxt_process_port_first(process);
964754Smax.romanov@nginx.com 
9651488St.nateldemoura@f5.com         if (nxt_proc_remove_notify_matrix[init.type][port->type] == 0) {
9661488St.nateldemoura@f5.com             continue;
9671488St.nateldemoura@f5.com         }
9681488St.nateldemoura@f5.com 
9691488St.nateldemoura@f5.com         buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
9701488St.nateldemoura@f5.com                                    sizeof(pid));
971754Smax.romanov@nginx.com 
9721488St.nateldemoura@f5.com         if (nxt_slow_path(buf == NULL)) {
9731488St.nateldemoura@f5.com             continue;
9741488St.nateldemoura@f5.com         }
9751488St.nateldemoura@f5.com 
9761488St.nateldemoura@f5.com         buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid));
9771488St.nateldemoura@f5.com 
9781488St.nateldemoura@f5.com         nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID, -1,
9791488St.nateldemoura@f5.com                               stream, 0, buf);
980754Smax.romanov@nginx.com 
981754Smax.romanov@nginx.com     } nxt_runtime_process_loop;
9821488St.nateldemoura@f5.com 
9831488St.nateldemoura@f5.com     if (init.restart) {
9841488St.nateldemoura@f5.com         ret = nxt_main_process_create(task, init);
9851488St.nateldemoura@f5.com         if (nxt_slow_path(ret == NXT_ERROR)) {
9861488St.nateldemoura@f5.com             nxt_alert(task, "failed to restart %s", name);
9871488St.nateldemoura@f5.com         }
9881488St.nateldemoura@f5.com     }
989754Smax.romanov@nginx.com }
990754Smax.romanov@nginx.com 
991754Smax.romanov@nginx.com 
992754Smax.romanov@nginx.com static void
993240Sigor@sysoev.ru nxt_main_port_socket_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
994240Sigor@sysoev.ru {
995240Sigor@sysoev.ru     size_t                  size;
996240Sigor@sysoev.ru     nxt_int_t               ret;
997240Sigor@sysoev.ru     nxt_buf_t               *b, *out;
998240Sigor@sysoev.ru     nxt_port_t              *port;
999240Sigor@sysoev.ru     nxt_sockaddr_t          *sa;
1000240Sigor@sysoev.ru     nxt_port_msg_type_t     type;
1001240Sigor@sysoev.ru     nxt_listening_socket_t  ls;
1002240Sigor@sysoev.ru     u_char                  message[2048];
1003240Sigor@sysoev.ru 
1004240Sigor@sysoev.ru     b = msg->buf;
1005240Sigor@sysoev.ru     sa = (nxt_sockaddr_t *) b->mem.pos;
1006240Sigor@sysoev.ru 
1007352Smax.romanov@nginx.com     /* TODO check b size and make plain */
1008352Smax.romanov@nginx.com 
1009240Sigor@sysoev.ru     out = NULL;
1010240Sigor@sysoev.ru 
1011240Sigor@sysoev.ru     ls.socket = -1;
1012240Sigor@sysoev.ru     ls.error = NXT_SOCKET_ERROR_SYSTEM;
1013240Sigor@sysoev.ru     ls.start = message;
1014240Sigor@sysoev.ru     ls.end = message + sizeof(message);
1015240Sigor@sysoev.ru 
1016240Sigor@sysoev.ru     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1017240Sigor@sysoev.ru                                  msg->port_msg.reply_port);
1018240Sigor@sysoev.ru 
1019240Sigor@sysoev.ru     nxt_debug(task, "listening socket \"%*s\"",
1020493Spluknet@nginx.com               (size_t) sa->length, nxt_sockaddr_start(sa));
1021240Sigor@sysoev.ru 
1022240Sigor@sysoev.ru     ret = nxt_main_listening_socket(sa, &ls);
1023240Sigor@sysoev.ru 
1024240Sigor@sysoev.ru     if (ret == NXT_OK) {
1025240Sigor@sysoev.ru         nxt_debug(task, "socket(\"%*s\"): %d",
1026493Spluknet@nginx.com                   (size_t) sa->length, nxt_sockaddr_start(sa), ls.socket);
1027240Sigor@sysoev.ru 
1028240Sigor@sysoev.ru         type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD;
1029240Sigor@sysoev.ru 
1030240Sigor@sysoev.ru     } else {
1031240Sigor@sysoev.ru         size = ls.end - ls.start;
1032240Sigor@sysoev.ru 
1033564Svbart@nginx.com         nxt_alert(task, "%*s", size, ls.start);
1034240Sigor@sysoev.ru 
1035342Smax.romanov@nginx.com         out = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
1036342Smax.romanov@nginx.com                                    size + 1);
1037240Sigor@sysoev.ru         if (nxt_slow_path(out == NULL)) {
1038240Sigor@sysoev.ru             return;
1039240Sigor@sysoev.ru         }
1040240Sigor@sysoev.ru 
1041240Sigor@sysoev.ru         *out->mem.free++ = (uint8_t) ls.error;
1042240Sigor@sysoev.ru 
1043240Sigor@sysoev.ru         out->mem.free = nxt_cpymem(out->mem.free, ls.start, size);
1044240Sigor@sysoev.ru 
1045240Sigor@sysoev.ru         type = NXT_PORT_MSG_RPC_ERROR;
1046240Sigor@sysoev.ru     }
1047240Sigor@sysoev.ru 
1048240Sigor@sysoev.ru     nxt_port_socket_write(task, port, type, ls.socket, msg->port_msg.stream,
1049240Sigor@sysoev.ru                           0, out);
1050240Sigor@sysoev.ru }
1051240Sigor@sysoev.ru 
1052240Sigor@sysoev.ru 
1053240Sigor@sysoev.ru static nxt_int_t
1054240Sigor@sysoev.ru nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls)
1055240Sigor@sysoev.ru {
1056240Sigor@sysoev.ru     nxt_err_t         err;
1057240Sigor@sysoev.ru     nxt_socket_t      s;
1058240Sigor@sysoev.ru 
1059240Sigor@sysoev.ru     const socklen_t   length = sizeof(int);
1060240Sigor@sysoev.ru     static const int  enable = 1;
1061240Sigor@sysoev.ru 
1062240Sigor@sysoev.ru     s = socket(sa->u.sockaddr.sa_family, sa->type, 0);
1063240Sigor@sysoev.ru 
1064240Sigor@sysoev.ru     if (nxt_slow_path(s == -1)) {
1065240Sigor@sysoev.ru         err = nxt_errno;
1066240Sigor@sysoev.ru 
1067240Sigor@sysoev.ru #if (NXT_INET6)
1068240Sigor@sysoev.ru 
1069240Sigor@sysoev.ru         if (err == EAFNOSUPPORT && sa->u.sockaddr.sa_family == AF_INET6) {
1070240Sigor@sysoev.ru             ls->error = NXT_SOCKET_ERROR_NOINET6;
1071240Sigor@sysoev.ru         }
1072240Sigor@sysoev.ru 
1073240Sigor@sysoev.ru #endif
1074240Sigor@sysoev.ru 
1075240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end,
1076240Sigor@sysoev.ru                               "socket(\\\"%*s\\\") failed %E",
1077493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa), err);
1078240Sigor@sysoev.ru 
1079240Sigor@sysoev.ru         return NXT_ERROR;
1080240Sigor@sysoev.ru     }
1081240Sigor@sysoev.ru 
1082240Sigor@sysoev.ru     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, length) != 0) {
1083240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end,
1084240Sigor@sysoev.ru                               "setsockopt(\\\"%*s\\\", SO_REUSEADDR) failed %E",
1085493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa),
1086493Spluknet@nginx.com                               nxt_errno);
1087240Sigor@sysoev.ru         goto fail;
1088240Sigor@sysoev.ru     }
1089240Sigor@sysoev.ru 
1090240Sigor@sysoev.ru #if (NXT_INET6)
1091240Sigor@sysoev.ru 
1092240Sigor@sysoev.ru     if (sa->u.sockaddr.sa_family == AF_INET6) {
1093240Sigor@sysoev.ru 
1094240Sigor@sysoev.ru         if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, length) != 0) {
1095240Sigor@sysoev.ru             ls->end = nxt_sprintf(ls->start, ls->end,
1096240Sigor@sysoev.ru                                "setsockopt(\\\"%*s\\\", IPV6_V6ONLY) 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 
1103240Sigor@sysoev.ru #endif
1104240Sigor@sysoev.ru 
1105240Sigor@sysoev.ru     if (bind(s, &sa->u.sockaddr, sa->socklen) != 0) {
1106240Sigor@sysoev.ru         err = nxt_errno;
1107240Sigor@sysoev.ru 
1108240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
1109240Sigor@sysoev.ru 
1110240Sigor@sysoev.ru         if (sa->u.sockaddr.sa_family == AF_UNIX) {
1111240Sigor@sysoev.ru             switch (err) {
1112240Sigor@sysoev.ru 
1113240Sigor@sysoev.ru             case EACCES:
1114240Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_ACCESS;
1115240Sigor@sysoev.ru                 break;
1116240Sigor@sysoev.ru 
1117240Sigor@sysoev.ru             case ENOENT:
1118240Sigor@sysoev.ru             case ENOTDIR:
1119240Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_PATH;
1120240Sigor@sysoev.ru                 break;
1121240Sigor@sysoev.ru             }
1122240Sigor@sysoev.ru 
1123908Sigor@sysoev.ru         } else
1124908Sigor@sysoev.ru #endif
1125908Sigor@sysoev.ru         {
1126908Sigor@sysoev.ru             switch (err) {
1127240Sigor@sysoev.ru 
1128908Sigor@sysoev.ru             case EACCES:
1129908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_PORT;
1130908Sigor@sysoev.ru                 break;
1131240Sigor@sysoev.ru 
1132908Sigor@sysoev.ru             case EADDRINUSE:
1133908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_INUSE;
1134908Sigor@sysoev.ru                 break;
1135240Sigor@sysoev.ru 
1136908Sigor@sysoev.ru             case EADDRNOTAVAIL:
1137908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_NOADDR;
1138908Sigor@sysoev.ru                 break;
1139908Sigor@sysoev.ru             }
1140240Sigor@sysoev.ru         }
1141240Sigor@sysoev.ru 
1142240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end, "bind(\\\"%*s\\\") failed %E",
1143493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa), err);
1144240Sigor@sysoev.ru         goto fail;
1145240Sigor@sysoev.ru     }
1146240Sigor@sysoev.ru 
1147240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
1148240Sigor@sysoev.ru 
1149240Sigor@sysoev.ru     if (sa->u.sockaddr.sa_family == AF_UNIX) {
1150240Sigor@sysoev.ru         char     *filename;
1151240Sigor@sysoev.ru         mode_t   access;
1152240Sigor@sysoev.ru 
1153240Sigor@sysoev.ru         filename = sa->u.sockaddr_un.sun_path;
1154240Sigor@sysoev.ru         access = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1155240Sigor@sysoev.ru 
1156240Sigor@sysoev.ru         if (chmod(filename, access) != 0) {
1157240Sigor@sysoev.ru             ls->end = nxt_sprintf(ls->start, ls->end,
1158494Spluknet@nginx.com                                   "chmod(\\\"%s\\\") failed %E",
1159240Sigor@sysoev.ru                                   filename, nxt_errno);
1160240Sigor@sysoev.ru             goto fail;
1161240Sigor@sysoev.ru         }
1162240Sigor@sysoev.ru     }
1163240Sigor@sysoev.ru 
1164240Sigor@sysoev.ru #endif
1165240Sigor@sysoev.ru 
1166240Sigor@sysoev.ru     ls->socket = s;
1167240Sigor@sysoev.ru 
1168240Sigor@sysoev.ru     return NXT_OK;
1169240Sigor@sysoev.ru 
1170240Sigor@sysoev.ru fail:
1171240Sigor@sysoev.ru 
1172240Sigor@sysoev.ru     (void) close(s);
1173240Sigor@sysoev.ru 
1174240Sigor@sysoev.ru     return NXT_ERROR;
1175240Sigor@sysoev.ru }
1176240Sigor@sysoev.ru 
1177240Sigor@sysoev.ru 
1178240Sigor@sysoev.ru static nxt_conf_map_t  nxt_app_lang_module_map[] = {
1179240Sigor@sysoev.ru     {
1180240Sigor@sysoev.ru         nxt_string("type"),
1181356Svbart@nginx.com         NXT_CONF_MAP_INT,
1182240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, type),
1183240Sigor@sysoev.ru     },
1184240Sigor@sysoev.ru 
1185240Sigor@sysoev.ru     {
1186240Sigor@sysoev.ru         nxt_string("version"),
1187354Svbart@nginx.com         NXT_CONF_MAP_CSTRZ,
1188240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, version),
1189240Sigor@sysoev.ru     },
1190240Sigor@sysoev.ru 
1191240Sigor@sysoev.ru     {
1192240Sigor@sysoev.ru         nxt_string("file"),
1193240Sigor@sysoev.ru         NXT_CONF_MAP_CSTRZ,
1194240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, file),
1195240Sigor@sysoev.ru     },
1196240Sigor@sysoev.ru };
1197240Sigor@sysoev.ru 
1198240Sigor@sysoev.ru 
11991489St.nateldemoura@f5.com static nxt_conf_map_t  nxt_app_lang_mounts_map[] = {
12001489St.nateldemoura@f5.com     {
12011489St.nateldemoura@f5.com         nxt_string("src"),
12021489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
12031489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, src),
12041489St.nateldemoura@f5.com     },
12051489St.nateldemoura@f5.com     {
12061489St.nateldemoura@f5.com         nxt_string("dst"),
12071489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
12081489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, dst),
12091489St.nateldemoura@f5.com     },
12101489St.nateldemoura@f5.com     {
12111673St.nateldemoura@f5.com         nxt_string("name"),
12121489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
12131673St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, name),
12141673St.nateldemoura@f5.com     },
12151673St.nateldemoura@f5.com     {
12161673St.nateldemoura@f5.com         nxt_string("type"),
12171673St.nateldemoura@f5.com         NXT_CONF_MAP_INT,
12181673St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, type),
12191489St.nateldemoura@f5.com     },
12201489St.nateldemoura@f5.com     {
12211489St.nateldemoura@f5.com         nxt_string("flags"),
12221489St.nateldemoura@f5.com         NXT_CONF_MAP_INT,
12231489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, flags),
12241489St.nateldemoura@f5.com     },
12251489St.nateldemoura@f5.com     {
12261489St.nateldemoura@f5.com         nxt_string("data"),
12271489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
12281489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, data),
12291489St.nateldemoura@f5.com     },
12301489St.nateldemoura@f5.com };
12311489St.nateldemoura@f5.com 
12321489St.nateldemoura@f5.com 
1233240Sigor@sysoev.ru static void
1234240Sigor@sysoev.ru nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1235240Sigor@sysoev.ru {
12361489St.nateldemoura@f5.com     uint32_t               index, jindex, nmounts;
1237240Sigor@sysoev.ru     nxt_mp_t               *mp;
1238240Sigor@sysoev.ru     nxt_int_t              ret;
1239240Sigor@sysoev.ru     nxt_buf_t              *b;
1240549Svbart@nginx.com     nxt_port_t             *port;
1241240Sigor@sysoev.ru     nxt_runtime_t          *rt;
12421489St.nateldemoura@f5.com     nxt_fs_mount_t         *mnt;
12431489St.nateldemoura@f5.com     nxt_conf_value_t       *conf, *root, *value, *mounts;
1244240Sigor@sysoev.ru     nxt_app_lang_module_t  *lang;
1245240Sigor@sysoev.ru 
12461182St.nateldemoura@f5.com     static nxt_str_t root_path = nxt_string("/");
12471489St.nateldemoura@f5.com     static nxt_str_t mounts_name = nxt_string("mounts");
1248240Sigor@sysoev.ru 
1249240Sigor@sysoev.ru     rt = task->thread->runtime;
1250240Sigor@sysoev.ru 
1251240Sigor@sysoev.ru     if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) {
1252240Sigor@sysoev.ru         return;
1253240Sigor@sysoev.ru     }
1254240Sigor@sysoev.ru 
12551211Smax.romanov@nginx.com     if (nxt_exiting) {
12561211Smax.romanov@nginx.com         nxt_debug(task, "ignoring discovered modules, exiting");
12571211Smax.romanov@nginx.com         return;
12581211Smax.romanov@nginx.com     }
12591211Smax.romanov@nginx.com 
1260549Svbart@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1261549Svbart@nginx.com                                  msg->port_msg.reply_port);
1262549Svbart@nginx.com 
1263549Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
1264549Svbart@nginx.com         (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1,
1265549Svbart@nginx.com                                      msg->port_msg.stream, 0, NULL);
1266549Svbart@nginx.com     }
1267549Svbart@nginx.com 
1268240Sigor@sysoev.ru     b = msg->buf;
1269240Sigor@sysoev.ru 
1270240Sigor@sysoev.ru     if (b == NULL) {
1271240Sigor@sysoev.ru         return;
1272240Sigor@sysoev.ru     }
1273240Sigor@sysoev.ru 
1274240Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
1275240Sigor@sysoev.ru     if (mp == NULL) {
1276240Sigor@sysoev.ru         return;
1277240Sigor@sysoev.ru     }
1278240Sigor@sysoev.ru 
1279352Smax.romanov@nginx.com     b = nxt_buf_chk_make_plain(mp, b, msg->size);
1280352Smax.romanov@nginx.com 
1281352Smax.romanov@nginx.com     if (b == NULL) {
1282352Smax.romanov@nginx.com         return;
1283352Smax.romanov@nginx.com     }
1284352Smax.romanov@nginx.com 
1285352Smax.romanov@nginx.com     nxt_debug(task, "application languages: \"%*s\"",
1286352Smax.romanov@nginx.com               b->mem.free - b->mem.pos, b->mem.pos);
1287352Smax.romanov@nginx.com 
1288240Sigor@sysoev.ru     conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL);
1289240Sigor@sysoev.ru     if (conf == NULL) {
1290240Sigor@sysoev.ru         goto fail;
1291240Sigor@sysoev.ru     }
1292240Sigor@sysoev.ru 
1293240Sigor@sysoev.ru     root = nxt_conf_get_path(conf, &root_path);
1294240Sigor@sysoev.ru     if (root == NULL) {
1295240Sigor@sysoev.ru         goto fail;
1296240Sigor@sysoev.ru     }
1297240Sigor@sysoev.ru 
1298240Sigor@sysoev.ru     for (index = 0; /* void */ ; index++) {
1299240Sigor@sysoev.ru         value = nxt_conf_get_array_element(root, index);
1300240Sigor@sysoev.ru         if (value == NULL) {
1301240Sigor@sysoev.ru             break;
1302240Sigor@sysoev.ru         }
1303240Sigor@sysoev.ru 
13041489St.nateldemoura@f5.com         lang = nxt_array_zero_add(rt->languages);
1305240Sigor@sysoev.ru         if (lang == NULL) {
1306240Sigor@sysoev.ru             goto fail;
1307240Sigor@sysoev.ru         }
1308240Sigor@sysoev.ru 
1309240Sigor@sysoev.ru         lang->module = NULL;
1310240Sigor@sysoev.ru 
1311240Sigor@sysoev.ru         ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map,
1312240Sigor@sysoev.ru                                   nxt_nitems(nxt_app_lang_module_map), lang);
1313240Sigor@sysoev.ru 
1314240Sigor@sysoev.ru         if (ret != NXT_OK) {
1315240Sigor@sysoev.ru             goto fail;
1316240Sigor@sysoev.ru         }
1317240Sigor@sysoev.ru 
13181489St.nateldemoura@f5.com         mounts = nxt_conf_get_object_member(value, &mounts_name, NULL);
13191489St.nateldemoura@f5.com         if (mounts == NULL) {
13201489St.nateldemoura@f5.com             nxt_alert(task, "missing mounts from discovery message.");
13211489St.nateldemoura@f5.com             goto fail;
13221489St.nateldemoura@f5.com         }
13231489St.nateldemoura@f5.com 
13241489St.nateldemoura@f5.com         if (nxt_conf_type(mounts) != NXT_CONF_ARRAY) {
13251489St.nateldemoura@f5.com             nxt_alert(task, "invalid mounts type from discovery message.");
13261489St.nateldemoura@f5.com             goto fail;
13271489St.nateldemoura@f5.com         }
13281489St.nateldemoura@f5.com 
13291489St.nateldemoura@f5.com         nmounts = nxt_conf_array_elements_count(mounts);
13301489St.nateldemoura@f5.com 
13311489St.nateldemoura@f5.com         lang->mounts = nxt_array_create(rt->mem_pool, nmounts,
13321489St.nateldemoura@f5.com                                         sizeof(nxt_fs_mount_t));
13331489St.nateldemoura@f5.com 
13341489St.nateldemoura@f5.com         if (lang->mounts == NULL) {
13351489St.nateldemoura@f5.com             goto fail;
13361489St.nateldemoura@f5.com         }
13371489St.nateldemoura@f5.com 
13381489St.nateldemoura@f5.com         for (jindex = 0; /* */; jindex++) {
13391489St.nateldemoura@f5.com             value = nxt_conf_get_array_element(mounts, jindex);
13401489St.nateldemoura@f5.com             if (value == NULL) {
13411489St.nateldemoura@f5.com                 break;
13421489St.nateldemoura@f5.com             }
13431489St.nateldemoura@f5.com 
13441489St.nateldemoura@f5.com             mnt = nxt_array_zero_add(lang->mounts);
13451489St.nateldemoura@f5.com             if (mnt == NULL) {
13461489St.nateldemoura@f5.com                 goto fail;
13471489St.nateldemoura@f5.com             }
13481489St.nateldemoura@f5.com 
13491585St.nateldemoura@f5.com             mnt->builtin = 1;
13501673St.nateldemoura@f5.com             mnt->deps = 1;
13511585St.nateldemoura@f5.com 
13521489St.nateldemoura@f5.com             ret = nxt_conf_map_object(rt->mem_pool, value,
13531489St.nateldemoura@f5.com                                       nxt_app_lang_mounts_map,
13541489St.nateldemoura@f5.com                                       nxt_nitems(nxt_app_lang_mounts_map), mnt);
13551489St.nateldemoura@f5.com 
13561489St.nateldemoura@f5.com             if (ret != NXT_OK) {
13571489St.nateldemoura@f5.com                 goto fail;
13581489St.nateldemoura@f5.com             }
13591489St.nateldemoura@f5.com         }
13601489St.nateldemoura@f5.com 
13611489St.nateldemoura@f5.com         nxt_debug(task, "lang %d %s \"%s\" (%d mounts)",
13621489St.nateldemoura@f5.com                   lang->type, lang->version, lang->file, lang->mounts->nelts);
1363240Sigor@sysoev.ru     }
1364240Sigor@sysoev.ru 
1365240Sigor@sysoev.ru     qsort(rt->languages->elts, rt->languages->nelts,
1366240Sigor@sysoev.ru           sizeof(nxt_app_lang_module_t), nxt_app_lang_compare);
1367240Sigor@sysoev.ru 
1368240Sigor@sysoev.ru fail:
1369240Sigor@sysoev.ru 
1370240Sigor@sysoev.ru     nxt_mp_destroy(mp);
1371240Sigor@sysoev.ru 
13721488St.nateldemoura@f5.com     ret = nxt_main_process_create(task, nxt_controller_process);
13731488St.nateldemoura@f5.com     if (ret == NXT_OK) {
13741488St.nateldemoura@f5.com         ret = nxt_main_process_create(task, nxt_router_process);
13751488St.nateldemoura@f5.com     }
1376240Sigor@sysoev.ru 
13771488St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
13781488St.nateldemoura@f5.com         nxt_exiting = 1;
13791488St.nateldemoura@f5.com 
13801488St.nateldemoura@f5.com         nxt_runtime_quit(task, 1);
1381240Sigor@sysoev.ru     }
1382240Sigor@sysoev.ru }
1383240Sigor@sysoev.ru 
1384240Sigor@sysoev.ru 
1385240Sigor@sysoev.ru static int nxt_cdecl
1386240Sigor@sysoev.ru nxt_app_lang_compare(const void *v1, const void *v2)
1387240Sigor@sysoev.ru {
1388240Sigor@sysoev.ru     int                          n;
1389240Sigor@sysoev.ru     const nxt_app_lang_module_t  *lang1, *lang2;
1390240Sigor@sysoev.ru 
1391240Sigor@sysoev.ru     lang1 = v1;
1392240Sigor@sysoev.ru     lang2 = v2;
1393240Sigor@sysoev.ru 
1394356Svbart@nginx.com     n = lang1->type - lang2->type;
1395258Sigor@sysoev.ru 
1396258Sigor@sysoev.ru     if (n != 0) {
1397258Sigor@sysoev.ru         return n;
1398258Sigor@sysoev.ru     }
1399258Sigor@sysoev.ru 
1400354Svbart@nginx.com     n = nxt_strverscmp(lang1->version, lang2->version);
1401240Sigor@sysoev.ru 
1402240Sigor@sysoev.ru     /* Negate result to move higher versions to the beginning. */
1403240Sigor@sysoev.ru 
1404240Sigor@sysoev.ru     return -n;
1405240Sigor@sysoev.ru }
1406314Svbart@nginx.com 
1407314Svbart@nginx.com 
1408314Svbart@nginx.com static void
1409314Svbart@nginx.com nxt_main_port_conf_store_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1410314Svbart@nginx.com {
1411352Smax.romanov@nginx.com     ssize_t        n, size, offset;
1412314Svbart@nginx.com     nxt_buf_t      *b;
1413314Svbart@nginx.com     nxt_int_t      ret;
1414314Svbart@nginx.com     nxt_file_t     file;
1415314Svbart@nginx.com     nxt_runtime_t  *rt;
1416314Svbart@nginx.com 
1417314Svbart@nginx.com     nxt_memzero(&file, sizeof(nxt_file_t));
1418314Svbart@nginx.com 
1419314Svbart@nginx.com     rt = task->thread->runtime;
1420314Svbart@nginx.com 
1421314Svbart@nginx.com     file.name = (nxt_file_name_t *) rt->conf_tmp;
1422314Svbart@nginx.com 
1423314Svbart@nginx.com     if (nxt_slow_path(nxt_file_open(task, &file, NXT_FILE_WRONLY,
1424314Svbart@nginx.com                                     NXT_FILE_TRUNCATE, NXT_FILE_OWNER_ACCESS)
1425314Svbart@nginx.com                       != NXT_OK))
1426314Svbart@nginx.com     {
1427314Svbart@nginx.com         goto error;
1428314Svbart@nginx.com     }
1429314Svbart@nginx.com 
1430352Smax.romanov@nginx.com     offset = 0;
1431352Smax.romanov@nginx.com 
1432314Svbart@nginx.com     for (b = msg->buf; b != NULL; b = b->next) {
1433314Svbart@nginx.com         size = nxt_buf_mem_used_size(&b->mem);
1434314Svbart@nginx.com 
1435352Smax.romanov@nginx.com         n = nxt_file_write(&file, b->mem.pos, size, offset);
1436314Svbart@nginx.com 
1437314Svbart@nginx.com         if (nxt_slow_path(n != size)) {
1438314Svbart@nginx.com             nxt_file_close(task, &file);
1439314Svbart@nginx.com             (void) nxt_file_delete(file.name);
1440314Svbart@nginx.com             goto error;
1441314Svbart@nginx.com         }
1442352Smax.romanov@nginx.com 
1443352Smax.romanov@nginx.com         offset += n;
1444314Svbart@nginx.com     }
1445314Svbart@nginx.com 
1446314Svbart@nginx.com     nxt_file_close(task, &file);
1447314Svbart@nginx.com 
1448314Svbart@nginx.com     ret = nxt_file_rename(file.name, (nxt_file_name_t *) rt->conf);
1449314Svbart@nginx.com 
1450314Svbart@nginx.com     if (nxt_fast_path(ret == NXT_OK)) {
1451314Svbart@nginx.com         return;
1452314Svbart@nginx.com     }
1453314Svbart@nginx.com 
1454314Svbart@nginx.com error:
1455314Svbart@nginx.com 
1456564Svbart@nginx.com     nxt_alert(task, "failed to store current configuration");
1457314Svbart@nginx.com }
1458630Svbart@nginx.com 
1459630Svbart@nginx.com 
1460630Svbart@nginx.com static void
1461630Svbart@nginx.com nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1462630Svbart@nginx.com {
1463630Svbart@nginx.com     u_char               *path;
1464630Svbart@nginx.com     nxt_int_t            ret;
1465630Svbart@nginx.com     nxt_file_t           file;
1466630Svbart@nginx.com     nxt_port_t           *port;
1467630Svbart@nginx.com     nxt_port_msg_type_t  type;
1468630Svbart@nginx.com 
1469630Svbart@nginx.com     nxt_debug(task, "opening access log file");
1470630Svbart@nginx.com 
1471630Svbart@nginx.com     path = msg->buf->mem.pos;
1472630Svbart@nginx.com 
1473630Svbart@nginx.com     nxt_memzero(&file, sizeof(nxt_file_t));
1474630Svbart@nginx.com 
1475630Svbart@nginx.com     file.name = (nxt_file_name_t *) path;
1476630Svbart@nginx.com     file.log_level = NXT_LOG_ERR;
1477630Svbart@nginx.com 
1478630Svbart@nginx.com     ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT,
1479630Svbart@nginx.com                         NXT_FILE_OWNER_ACCESS);
1480630Svbart@nginx.com 
1481630Svbart@nginx.com     type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD
1482630Svbart@nginx.com                            : NXT_PORT_MSG_RPC_ERROR;
1483630Svbart@nginx.com 
1484630Svbart@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1485630Svbart@nginx.com                                  msg->port_msg.reply_port);
1486630Svbart@nginx.com 
1487630Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
1488630Svbart@nginx.com         (void) nxt_port_socket_write(task, port, type, file.fd,
1489630Svbart@nginx.com                                      msg->port_msg.stream, 0, NULL);
1490630Svbart@nginx.com     }
1491630Svbart@nginx.com }
1492