xref: /unit/src/nxt_main_process.c (revision 1320)
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 
17240Sigor@sysoev.ru 
18240Sigor@sysoev.ru typedef struct {
19240Sigor@sysoev.ru     nxt_socket_t        socket;
20240Sigor@sysoev.ru     nxt_socket_error_t  error;
21240Sigor@sysoev.ru     u_char              *start;
22240Sigor@sysoev.ru     u_char              *end;
23240Sigor@sysoev.ru } nxt_listening_socket_t;
24240Sigor@sysoev.ru 
25240Sigor@sysoev.ru 
26510Salexander.borisov@nginx.com typedef struct {
27536Svbart@nginx.com     nxt_uint_t          size;
28536Svbart@nginx.com     nxt_conf_map_t      *map;
29546Smax.romanov@nginx.com } nxt_conf_app_map_t;
30510Salexander.borisov@nginx.com 
31510Salexander.borisov@nginx.com 
321302St.nateldemoura@f5.com extern nxt_port_handlers_t  nxt_controller_process_port_handlers;
331302St.nateldemoura@f5.com extern nxt_port_handlers_t  nxt_router_process_port_handlers;
341302St.nateldemoura@f5.com 
351302St.nateldemoura@f5.com 
36240Sigor@sysoev.ru static nxt_int_t nxt_main_process_port_create(nxt_task_t *task,
37240Sigor@sysoev.ru     nxt_runtime_t *rt);
38240Sigor@sysoev.ru static void nxt_main_process_title(nxt_task_t *task);
39240Sigor@sysoev.ru static nxt_int_t nxt_main_start_controller_process(nxt_task_t *task,
40240Sigor@sysoev.ru     nxt_runtime_t *rt);
41368Svbart@nginx.com static nxt_int_t nxt_main_create_controller_process(nxt_task_t *task,
42368Svbart@nginx.com     nxt_runtime_t *rt, nxt_process_init_t *init);
431302St.nateldemoura@f5.com static nxt_int_t nxt_main_create_router_process(nxt_task_t *task, nxt_runtime_t *rt,
441302St.nateldemoura@f5.com     nxt_process_init_t *init);
45240Sigor@sysoev.ru static nxt_int_t nxt_main_start_router_process(nxt_task_t *task,
46240Sigor@sysoev.ru     nxt_runtime_t *rt);
47240Sigor@sysoev.ru static nxt_int_t nxt_main_start_discovery_process(nxt_task_t *task,
48240Sigor@sysoev.ru     nxt_runtime_t *rt);
49240Sigor@sysoev.ru static nxt_int_t nxt_main_start_worker_process(nxt_task_t *task,
50240Sigor@sysoev.ru     nxt_runtime_t *rt, nxt_common_app_conf_t *app_conf, uint32_t stream);
51240Sigor@sysoev.ru static nxt_int_t nxt_main_create_worker_process(nxt_task_t *task,
52240Sigor@sysoev.ru     nxt_runtime_t *rt, nxt_process_init_t *init);
53240Sigor@sysoev.ru static void nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj,
54240Sigor@sysoev.ru     void *data);
55240Sigor@sysoev.ru static void nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj,
56240Sigor@sysoev.ru     void *data);
57240Sigor@sysoev.ru static void nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj,
58240Sigor@sysoev.ru     void *data);
59240Sigor@sysoev.ru static void nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj,
60240Sigor@sysoev.ru     void *data);
61944Sigor@sysoev.ru static void nxt_main_process_signal_handler(nxt_task_t *task, void *obj,
62944Sigor@sysoev.ru     void *data);
63240Sigor@sysoev.ru static void nxt_main_cleanup_worker_process(nxt_task_t *task, nxt_pid_t pid);
64754Smax.romanov@nginx.com static void nxt_main_stop_worker_processes(nxt_task_t *task, nxt_runtime_t *rt);
65240Sigor@sysoev.ru static void nxt_main_port_socket_handler(nxt_task_t *task,
66240Sigor@sysoev.ru     nxt_port_recv_msg_t *msg);
67240Sigor@sysoev.ru static nxt_int_t nxt_main_listening_socket(nxt_sockaddr_t *sa,
68240Sigor@sysoev.ru     nxt_listening_socket_t *ls);
69240Sigor@sysoev.ru static void nxt_main_port_modules_handler(nxt_task_t *task,
70240Sigor@sysoev.ru     nxt_port_recv_msg_t *msg);
71240Sigor@sysoev.ru static int nxt_cdecl nxt_app_lang_compare(const void *v1, const void *v2);
72314Svbart@nginx.com static void nxt_main_port_conf_store_handler(nxt_task_t *task,
73314Svbart@nginx.com     nxt_port_recv_msg_t *msg);
74630Svbart@nginx.com static void nxt_main_port_access_log_handler(nxt_task_t *task,
75630Svbart@nginx.com     nxt_port_recv_msg_t *msg);
761302St.nateldemoura@f5.com static nxt_process_init_t *nxt_process_init_create(nxt_task_t *task,
771302St.nateldemoura@f5.com     nxt_process_type_t type, const nxt_str_t *name);
781302St.nateldemoura@f5.com static nxt_int_t nxt_process_init_name_set(nxt_process_init_t *init,
791302St.nateldemoura@f5.com     nxt_process_type_t type, const nxt_str_t *name);
801302St.nateldemoura@f5.com static nxt_int_t nxt_process_init_creds_set(nxt_task_t *task,
811302St.nateldemoura@f5.com     nxt_process_init_t *init, nxt_str_t *user, nxt_str_t *group);
82240Sigor@sysoev.ru 
831306St.nateldemoura@f5.com static nxt_int_t nxt_init_isolation(nxt_task_t *task,
841306St.nateldemoura@f5.com     nxt_conf_value_t *isolation, nxt_process_init_t *init);
851306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE)
861306St.nateldemoura@f5.com static nxt_int_t nxt_init_clone_flags(nxt_task_t *task,
871306St.nateldemoura@f5.com     nxt_conf_value_t *namespaces, nxt_process_init_t *init);
881306St.nateldemoura@f5.com #endif
891306St.nateldemoura@f5.com 
901306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER)
911306St.nateldemoura@f5.com static nxt_int_t nxt_init_isolation_creds(nxt_task_t *task,
921306St.nateldemoura@f5.com     nxt_conf_value_t *isolation, nxt_process_init_t *init);
931306St.nateldemoura@f5.com static nxt_int_t nxt_init_vldt_isolation_creds(nxt_task_t *task,
941306St.nateldemoura@f5.com     nxt_process_init_t *init);
951306St.nateldemoura@f5.com static nxt_int_t nxt_init_isolation_credential_map(nxt_task_t *task,
961306St.nateldemoura@f5.com     nxt_mp_t *mem_pool, nxt_conf_value_t *map_array,
971306St.nateldemoura@f5.com     nxt_clone_credential_map_t *map);
981306St.nateldemoura@f5.com #endif
99240Sigor@sysoev.ru 
100240Sigor@sysoev.ru const nxt_sig_event_t  nxt_main_process_signals[] = {
101944Sigor@sysoev.ru     nxt_event_signal(SIGHUP,  nxt_main_process_signal_handler),
102240Sigor@sysoev.ru     nxt_event_signal(SIGINT,  nxt_main_process_sigterm_handler),
103240Sigor@sysoev.ru     nxt_event_signal(SIGQUIT, nxt_main_process_sigquit_handler),
104240Sigor@sysoev.ru     nxt_event_signal(SIGTERM, nxt_main_process_sigterm_handler),
105240Sigor@sysoev.ru     nxt_event_signal(SIGCHLD, nxt_main_process_sigchld_handler),
106240Sigor@sysoev.ru     nxt_event_signal(SIGUSR1, nxt_main_process_sigusr1_handler),
107240Sigor@sysoev.ru     nxt_event_signal_end,
108240Sigor@sysoev.ru };
109240Sigor@sysoev.ru 
110240Sigor@sysoev.ru 
1111302St.nateldemoura@f5.com static const nxt_port_handlers_t  nxt_app_process_port_handlers = {
1121302St.nateldemoura@f5.com     .new_port     = nxt_port_new_port_handler,
1131302St.nateldemoura@f5.com     .change_file  = nxt_port_change_log_file_handler,
1141302St.nateldemoura@f5.com     .mmap         = nxt_port_mmap_handler,
1151302St.nateldemoura@f5.com     .remove_pid   = nxt_port_remove_pid_handler,
1161302St.nateldemoura@f5.com };
1171302St.nateldemoura@f5.com 
1181302St.nateldemoura@f5.com 
1191302St.nateldemoura@f5.com static const nxt_port_handlers_t  nxt_discovery_process_port_handlers = {
1201302St.nateldemoura@f5.com     .quit         = nxt_worker_process_quit_handler,
1211302St.nateldemoura@f5.com     .new_port     = nxt_port_new_port_handler,
1221302St.nateldemoura@f5.com     .change_file  = nxt_port_change_log_file_handler,
1231302St.nateldemoura@f5.com     .mmap         = nxt_port_mmap_handler,
1241302St.nateldemoura@f5.com     .data         = nxt_port_data_handler,
1251302St.nateldemoura@f5.com     .remove_pid   = nxt_port_remove_pid_handler,
1261302St.nateldemoura@f5.com     .rpc_ready    = nxt_port_rpc_handler,
1271302St.nateldemoura@f5.com     .rpc_error    = nxt_port_rpc_handler,
1281302St.nateldemoura@f5.com };
1291302St.nateldemoura@f5.com 
1301302St.nateldemoura@f5.com 
1311302St.nateldemoura@f5.com static const nxt_port_handlers_t  *nxt_process_port_handlers[NXT_PROCESS_MAX] =
1321302St.nateldemoura@f5.com {
1331302St.nateldemoura@f5.com     NULL,
1341302St.nateldemoura@f5.com     &nxt_discovery_process_port_handlers,
1351302St.nateldemoura@f5.com     &nxt_controller_process_port_handlers,
1361302St.nateldemoura@f5.com     &nxt_router_process_port_handlers,
1371302St.nateldemoura@f5.com     &nxt_app_process_port_handlers
1381302St.nateldemoura@f5.com };
1391302St.nateldemoura@f5.com 
1401302St.nateldemoura@f5.com 
1411302St.nateldemoura@f5.com static const nxt_process_start_t  nxt_process_starts[NXT_PROCESS_MAX] = {
1421302St.nateldemoura@f5.com     NULL,
1431302St.nateldemoura@f5.com     nxt_discovery_start,
1441302St.nateldemoura@f5.com     nxt_controller_start,
1451302St.nateldemoura@f5.com     nxt_router_start,
1461302St.nateldemoura@f5.com     nxt_app_start
1471302St.nateldemoura@f5.com };
1481302St.nateldemoura@f5.com 
1491302St.nateldemoura@f5.com 
1501302St.nateldemoura@f5.com static const nxt_process_restart_t  nxt_process_restarts[NXT_PROCESS_MAX] = {
1511302St.nateldemoura@f5.com     NULL,
1521302St.nateldemoura@f5.com     NULL,
1531302St.nateldemoura@f5.com     &nxt_main_create_controller_process,
1541302St.nateldemoura@f5.com     &nxt_main_create_router_process,
1551302St.nateldemoura@f5.com     NULL
1561302St.nateldemoura@f5.com };
1571302St.nateldemoura@f5.com 
1581302St.nateldemoura@f5.com 
159240Sigor@sysoev.ru static nxt_bool_t  nxt_exiting;
160240Sigor@sysoev.ru 
161240Sigor@sysoev.ru 
162240Sigor@sysoev.ru nxt_int_t
163240Sigor@sysoev.ru nxt_main_process_start(nxt_thread_t *thr, nxt_task_t *task,
164240Sigor@sysoev.ru     nxt_runtime_t *rt)
165240Sigor@sysoev.ru {
166696Sigor@sysoev.ru     rt->type = NXT_PROCESS_MAIN;
167240Sigor@sysoev.ru 
168240Sigor@sysoev.ru     if (nxt_main_process_port_create(task, rt) != NXT_OK) {
169240Sigor@sysoev.ru         return NXT_ERROR;
170240Sigor@sysoev.ru     }
171240Sigor@sysoev.ru 
172240Sigor@sysoev.ru     nxt_main_process_title(task);
173240Sigor@sysoev.ru 
174240Sigor@sysoev.ru     /*
175240Sigor@sysoev.ru      * The dicsovery process will send a message processed by
176240Sigor@sysoev.ru      * nxt_main_port_modules_handler() which starts the controller
177240Sigor@sysoev.ru      * and router processes.
178240Sigor@sysoev.ru      */
179240Sigor@sysoev.ru     return nxt_main_start_discovery_process(task, rt);
180240Sigor@sysoev.ru }
181240Sigor@sysoev.ru 
182240Sigor@sysoev.ru 
183240Sigor@sysoev.ru static nxt_conf_map_t  nxt_common_app_conf[] = {
184240Sigor@sysoev.ru     {
185240Sigor@sysoev.ru         nxt_string("type"),
186240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
187240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, type),
188240Sigor@sysoev.ru     },
189240Sigor@sysoev.ru 
190240Sigor@sysoev.ru     {
191240Sigor@sysoev.ru         nxt_string("user"),
192240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
193240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, user),
194240Sigor@sysoev.ru     },
195240Sigor@sysoev.ru 
196240Sigor@sysoev.ru     {
197240Sigor@sysoev.ru         nxt_string("group"),
198240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
199240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, group),
200240Sigor@sysoev.ru     },
201240Sigor@sysoev.ru 
202240Sigor@sysoev.ru     {
203271Smax.romanov@nginx.com         nxt_string("working_directory"),
204271Smax.romanov@nginx.com         NXT_CONF_MAP_CSTRZ,
205271Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, working_directory),
206271Smax.romanov@nginx.com     },
207678Svbart@nginx.com 
208678Svbart@nginx.com     {
209678Svbart@nginx.com         nxt_string("environment"),
210678Svbart@nginx.com         NXT_CONF_MAP_PTR,
211678Svbart@nginx.com         offsetof(nxt_common_app_conf_t, environment),
212678Svbart@nginx.com     },
2131182St.nateldemoura@f5.com 
2141182St.nateldemoura@f5.com     {
2151182St.nateldemoura@f5.com         nxt_string("isolation"),
2161182St.nateldemoura@f5.com         NXT_CONF_MAP_PTR,
2171182St.nateldemoura@f5.com         offsetof(nxt_common_app_conf_t, isolation),
218*1320Smax.romanov@nginx.com     },
219*1320Smax.romanov@nginx.com 
220*1320Smax.romanov@nginx.com     {
221*1320Smax.romanov@nginx.com         nxt_string("limits"),
222*1320Smax.romanov@nginx.com         NXT_CONF_MAP_PTR,
223*1320Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, limits),
224*1320Smax.romanov@nginx.com     },
225*1320Smax.romanov@nginx.com 
226*1320Smax.romanov@nginx.com };
227*1320Smax.romanov@nginx.com 
228*1320Smax.romanov@nginx.com 
229*1320Smax.romanov@nginx.com static nxt_conf_map_t  nxt_common_app_limits_conf[] = {
230*1320Smax.romanov@nginx.com     {
231*1320Smax.romanov@nginx.com         nxt_string("shm"),
232*1320Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
233*1320Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, shm_limit),
234*1320Smax.romanov@nginx.com     },
235*1320Smax.romanov@nginx.com 
236510Salexander.borisov@nginx.com };
237271Smax.romanov@nginx.com 
238510Salexander.borisov@nginx.com 
239804Svbart@nginx.com static nxt_conf_map_t  nxt_external_app_conf[] = {
240804Svbart@nginx.com     {
241804Svbart@nginx.com         nxt_string("executable"),
242804Svbart@nginx.com         NXT_CONF_MAP_CSTRZ,
243804Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.external.executable),
244804Svbart@nginx.com     },
245804Svbart@nginx.com 
246804Svbart@nginx.com     {
247804Svbart@nginx.com         nxt_string("arguments"),
248804Svbart@nginx.com         NXT_CONF_MAP_PTR,
249804Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.external.arguments),
250804Svbart@nginx.com     },
251804Svbart@nginx.com 
252804Svbart@nginx.com };
253804Svbart@nginx.com 
254804Svbart@nginx.com 
255546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_python_app_conf[] = {
256271Smax.romanov@nginx.com     {
257394Smax.romanov@nginx.com         nxt_string("home"),
258394Smax.romanov@nginx.com         NXT_CONF_MAP_CSTRZ,
259394Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.home),
260394Smax.romanov@nginx.com     },
261394Smax.romanov@nginx.com 
262394Smax.romanov@nginx.com     {
263240Sigor@sysoev.ru         nxt_string("path"),
264240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
265240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, u.python.path),
266240Sigor@sysoev.ru     },
267240Sigor@sysoev.ru 
268240Sigor@sysoev.ru     {
269240Sigor@sysoev.ru         nxt_string("module"),
270240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
271240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, u.python.module),
272240Sigor@sysoev.ru     },
273510Salexander.borisov@nginx.com };
274240Sigor@sysoev.ru 
275510Salexander.borisov@nginx.com 
276546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_php_app_conf[] = {
277240Sigor@sysoev.ru     {
278240Sigor@sysoev.ru         nxt_string("root"),
279462Smax.romanov@nginx.com         NXT_CONF_MAP_CSTRZ,
280240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, u.php.root),
281240Sigor@sysoev.ru     },
282240Sigor@sysoev.ru 
283240Sigor@sysoev.ru     {
284240Sigor@sysoev.ru         nxt_string("script"),
285240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
286240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, u.php.script),
287240Sigor@sysoev.ru     },
288240Sigor@sysoev.ru 
289240Sigor@sysoev.ru     {
290240Sigor@sysoev.ru         nxt_string("index"),
291240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
292240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, u.php.index),
293240Sigor@sysoev.ru     },
294687Svbart@nginx.com 
295687Svbart@nginx.com     {
296687Svbart@nginx.com         nxt_string("options"),
297687Svbart@nginx.com         NXT_CONF_MAP_PTR,
298687Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.php.options),
299687Svbart@nginx.com     },
300510Salexander.borisov@nginx.com };
301240Sigor@sysoev.ru 
302510Salexander.borisov@nginx.com 
303546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_perl_app_conf[] = {
304510Salexander.borisov@nginx.com     {
305510Salexander.borisov@nginx.com         nxt_string("script"),
306510Salexander.borisov@nginx.com         NXT_CONF_MAP_CSTRZ,
307510Salexander.borisov@nginx.com         offsetof(nxt_common_app_conf_t, u.perl.script),
308510Salexander.borisov@nginx.com     },
309510Salexander.borisov@nginx.com };
310510Salexander.borisov@nginx.com 
311510Salexander.borisov@nginx.com 
312584Salexander.borisov@nginx.com static nxt_conf_map_t  nxt_ruby_app_conf[] = {
313584Salexander.borisov@nginx.com     {
314584Salexander.borisov@nginx.com         nxt_string("script"),
315584Salexander.borisov@nginx.com         NXT_CONF_MAP_STR,
316584Salexander.borisov@nginx.com         offsetof(nxt_common_app_conf_t, u.ruby.script),
317584Salexander.borisov@nginx.com     },
318584Salexander.borisov@nginx.com };
319584Salexander.borisov@nginx.com 
320584Salexander.borisov@nginx.com 
321977Smax.romanov@gmail.com static nxt_conf_map_t  nxt_java_app_conf[] = {
322977Smax.romanov@gmail.com     {
323977Smax.romanov@gmail.com         nxt_string("classpath"),
324977Smax.romanov@gmail.com         NXT_CONF_MAP_PTR,
325977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.classpath),
326977Smax.romanov@gmail.com     },
327977Smax.romanov@gmail.com     {
328977Smax.romanov@gmail.com         nxt_string("webapp"),
329977Smax.romanov@gmail.com         NXT_CONF_MAP_CSTRZ,
330977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.webapp),
331977Smax.romanov@gmail.com     },
332977Smax.romanov@gmail.com     {
333977Smax.romanov@gmail.com         nxt_string("options"),
334977Smax.romanov@gmail.com         NXT_CONF_MAP_PTR,
335977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.options),
336977Smax.romanov@gmail.com     },
337977Smax.romanov@gmail.com     {
338977Smax.romanov@gmail.com         nxt_string("unit_jars"),
339977Smax.romanov@gmail.com         NXT_CONF_MAP_CSTRZ,
340977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.unit_jars),
341977Smax.romanov@gmail.com     },
342977Smax.romanov@gmail.com 
343977Smax.romanov@gmail.com };
344977Smax.romanov@gmail.com 
345977Smax.romanov@gmail.com 
346546Smax.romanov@nginx.com static nxt_conf_app_map_t  nxt_app_maps[] = {
347804Svbart@nginx.com     { nxt_nitems(nxt_external_app_conf),  nxt_external_app_conf },
348804Svbart@nginx.com     { nxt_nitems(nxt_python_app_conf),    nxt_python_app_conf },
349804Svbart@nginx.com     { nxt_nitems(nxt_php_app_conf),       nxt_php_app_conf },
350804Svbart@nginx.com     { nxt_nitems(nxt_perl_app_conf),      nxt_perl_app_conf },
351804Svbart@nginx.com     { nxt_nitems(nxt_ruby_app_conf),      nxt_ruby_app_conf },
352977Smax.romanov@gmail.com     { nxt_nitems(nxt_java_app_conf),      nxt_java_app_conf },
353510Salexander.borisov@nginx.com };
354510Salexander.borisov@nginx.com 
355510Salexander.borisov@nginx.com 
356240Sigor@sysoev.ru static void
357240Sigor@sysoev.ru nxt_port_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
358240Sigor@sysoev.ru {
359240Sigor@sysoev.ru     nxt_debug(task, "main data: %*s",
360240Sigor@sysoev.ru               nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos);
361240Sigor@sysoev.ru }
362240Sigor@sysoev.ru 
363240Sigor@sysoev.ru 
364240Sigor@sysoev.ru static void
365240Sigor@sysoev.ru nxt_port_main_start_worker_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
366240Sigor@sysoev.ru {
367536Svbart@nginx.com     u_char                 *start, ch;
368536Svbart@nginx.com     size_t                 type_len;
369240Sigor@sysoev.ru     nxt_mp_t               *mp;
370536Svbart@nginx.com     nxt_int_t              ret;
371240Sigor@sysoev.ru     nxt_buf_t              *b;
372318Smax.romanov@nginx.com     nxt_port_t             *port;
3731182St.nateldemoura@f5.com     nxt_runtime_t          *rt;
374536Svbart@nginx.com     nxt_app_type_t         idx;
375240Sigor@sysoev.ru     nxt_conf_value_t       *conf;
376240Sigor@sysoev.ru     nxt_common_app_conf_t  app_conf;
377240Sigor@sysoev.ru 
378318Smax.romanov@nginx.com     ret = NXT_ERROR;
379318Smax.romanov@nginx.com 
380352Smax.romanov@nginx.com     mp = nxt_mp_create(1024, 128, 256, 32);
381352Smax.romanov@nginx.com 
382352Smax.romanov@nginx.com     if (nxt_slow_path(mp == NULL)) {
383352Smax.romanov@nginx.com         return;
384352Smax.romanov@nginx.com     }
385352Smax.romanov@nginx.com 
386352Smax.romanov@nginx.com     b = nxt_buf_chk_make_plain(mp, msg->buf, msg->size);
387352Smax.romanov@nginx.com 
388352Smax.romanov@nginx.com     if (b == NULL) {
389352Smax.romanov@nginx.com         return;
390352Smax.romanov@nginx.com     }
391240Sigor@sysoev.ru 
392240Sigor@sysoev.ru     nxt_debug(task, "main start worker: %*s", b->mem.free - b->mem.pos,
393240Sigor@sysoev.ru               b->mem.pos);
394240Sigor@sysoev.ru 
395240Sigor@sysoev.ru     nxt_memzero(&app_conf, sizeof(nxt_common_app_conf_t));
396240Sigor@sysoev.ru 
397240Sigor@sysoev.ru     start = b->mem.pos;
398240Sigor@sysoev.ru 
399240Sigor@sysoev.ru     app_conf.name.start = start;
400240Sigor@sysoev.ru     app_conf.name.length = nxt_strlen(start);
401*1320Smax.romanov@nginx.com     app_conf.shm_limit = 100 * 1024 * 1024;
402240Sigor@sysoev.ru 
403240Sigor@sysoev.ru     start += app_conf.name.length + 1;
404240Sigor@sysoev.ru 
405240Sigor@sysoev.ru     conf = nxt_conf_json_parse(mp, start, b->mem.free, NULL);
406240Sigor@sysoev.ru 
407240Sigor@sysoev.ru     if (conf == NULL) {
408564Svbart@nginx.com         nxt_alert(task, "router app configuration parsing error");
409318Smax.romanov@nginx.com 
410318Smax.romanov@nginx.com         goto failed;
411240Sigor@sysoev.ru     }
412240Sigor@sysoev.ru 
4131182St.nateldemoura@f5.com     rt = task->thread->runtime;
4141182St.nateldemoura@f5.com 
4151182St.nateldemoura@f5.com     app_conf.user.start  = (u_char*)rt->user_cred.user;
4161182St.nateldemoura@f5.com     app_conf.user.length = nxt_strlen(rt->user_cred.user);
417240Sigor@sysoev.ru 
418240Sigor@sysoev.ru     ret = nxt_conf_map_object(mp, conf, nxt_common_app_conf,
419240Sigor@sysoev.ru                               nxt_nitems(nxt_common_app_conf), &app_conf);
420240Sigor@sysoev.ru     if (ret != NXT_OK) {
421564Svbart@nginx.com         nxt_alert(task, "failed to map common app conf received from router");
422318Smax.romanov@nginx.com         goto failed;
423240Sigor@sysoev.ru     }
424240Sigor@sysoev.ru 
425536Svbart@nginx.com     for (type_len = 0; type_len != app_conf.type.length; type_len++) {
426536Svbart@nginx.com         ch = app_conf.type.start[type_len];
427536Svbart@nginx.com 
428536Svbart@nginx.com         if (ch == ' ' || nxt_isdigit(ch)) {
429536Svbart@nginx.com             break;
430536Svbart@nginx.com         }
431536Svbart@nginx.com     }
432536Svbart@nginx.com 
433536Svbart@nginx.com     idx = nxt_app_parse_type(app_conf.type.start, type_len);
434510Salexander.borisov@nginx.com 
435546Smax.romanov@nginx.com     if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) {
436564Svbart@nginx.com         nxt_alert(task, "invalid app type %d received from router", (int) idx);
437546Smax.romanov@nginx.com         goto failed;
438546Smax.romanov@nginx.com     }
439510Salexander.borisov@nginx.com 
440546Smax.romanov@nginx.com     ret = nxt_conf_map_object(mp, conf, nxt_app_maps[idx].map,
441546Smax.romanov@nginx.com                               nxt_app_maps[idx].size, &app_conf);
442510Salexander.borisov@nginx.com 
443546Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
444564Svbart@nginx.com         nxt_alert(task, "failed to map app conf received from router");
445546Smax.romanov@nginx.com         goto failed;
446546Smax.romanov@nginx.com     }
447510Salexander.borisov@nginx.com 
448*1320Smax.romanov@nginx.com     if (app_conf.limits != NULL) {
449*1320Smax.romanov@nginx.com         ret = nxt_conf_map_object(mp, app_conf.limits,
450*1320Smax.romanov@nginx.com                                   nxt_common_app_limits_conf,
451*1320Smax.romanov@nginx.com                                   nxt_nitems(nxt_common_app_limits_conf),
452*1320Smax.romanov@nginx.com                                   &app_conf);
453*1320Smax.romanov@nginx.com 
454*1320Smax.romanov@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
455*1320Smax.romanov@nginx.com             nxt_alert(task, "failed to map app limits received from router");
456*1320Smax.romanov@nginx.com             goto failed;
457*1320Smax.romanov@nginx.com         }
458*1320Smax.romanov@nginx.com     }
459*1320Smax.romanov@nginx.com 
460240Sigor@sysoev.ru     ret = nxt_main_start_worker_process(task, task->thread->runtime,
461240Sigor@sysoev.ru                                         &app_conf, msg->port_msg.stream);
462240Sigor@sysoev.ru 
463318Smax.romanov@nginx.com failed:
464318Smax.romanov@nginx.com 
465318Smax.romanov@nginx.com     if (ret == NXT_ERROR) {
466318Smax.romanov@nginx.com         port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
467318Smax.romanov@nginx.com                                      msg->port_msg.reply_port);
468318Smax.romanov@nginx.com         if (nxt_fast_path(port != NULL)) {
469318Smax.romanov@nginx.com             nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
470318Smax.romanov@nginx.com                                     -1, msg->port_msg.stream, 0, NULL);
471318Smax.romanov@nginx.com         }
472318Smax.romanov@nginx.com     }
473318Smax.romanov@nginx.com 
474240Sigor@sysoev.ru     nxt_mp_destroy(mp);
475240Sigor@sysoev.ru }
476240Sigor@sysoev.ru 
477240Sigor@sysoev.ru 
478320Smax.romanov@nginx.com static nxt_port_handlers_t  nxt_main_process_port_handlers = {
479320Smax.romanov@nginx.com     .data           = nxt_port_main_data_handler,
480320Smax.romanov@nginx.com     .process_ready  = nxt_port_process_ready_handler,
481320Smax.romanov@nginx.com     .start_worker   = nxt_port_main_start_worker_handler,
482320Smax.romanov@nginx.com     .socket         = nxt_main_port_socket_handler,
483320Smax.romanov@nginx.com     .modules        = nxt_main_port_modules_handler,
484320Smax.romanov@nginx.com     .conf_store     = nxt_main_port_conf_store_handler,
485774Svbart@nginx.com #if (NXT_TLS)
486774Svbart@nginx.com     .cert_get       = nxt_cert_store_get_handler,
487774Svbart@nginx.com     .cert_delete    = nxt_cert_store_delete_handler,
488774Svbart@nginx.com #endif
489630Svbart@nginx.com     .access_log     = nxt_main_port_access_log_handler,
490320Smax.romanov@nginx.com     .rpc_ready      = nxt_port_rpc_handler,
491320Smax.romanov@nginx.com     .rpc_error      = nxt_port_rpc_handler,
492240Sigor@sysoev.ru };
493240Sigor@sysoev.ru 
494240Sigor@sysoev.ru 
495240Sigor@sysoev.ru static nxt_int_t
496240Sigor@sysoev.ru nxt_main_process_port_create(nxt_task_t *task, nxt_runtime_t *rt)
497240Sigor@sysoev.ru {
498240Sigor@sysoev.ru     nxt_int_t      ret;
499240Sigor@sysoev.ru     nxt_port_t     *port;
500240Sigor@sysoev.ru     nxt_process_t  *process;
501240Sigor@sysoev.ru 
5021254Shongzhidao@gmail.com     port = nxt_runtime_process_port_create(task, rt, nxt_pid, 0,
5031254Shongzhidao@gmail.com                                            NXT_PROCESS_MAIN);
504240Sigor@sysoev.ru     if (nxt_slow_path(port == NULL)) {
505240Sigor@sysoev.ru         return NXT_ERROR;
506240Sigor@sysoev.ru     }
507240Sigor@sysoev.ru 
5081254Shongzhidao@gmail.com     process = port->process;
509349Smax.romanov@nginx.com 
510240Sigor@sysoev.ru     ret = nxt_port_socket_init(task, port, 0);
511240Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
512240Sigor@sysoev.ru         return ret;
513240Sigor@sysoev.ru     }
514240Sigor@sysoev.ru 
515240Sigor@sysoev.ru     /*
516240Sigor@sysoev.ru      * A main process port.  A write port is not closed
517240Sigor@sysoev.ru      * since it should be inherited by worker processes.
518240Sigor@sysoev.ru      */
519320Smax.romanov@nginx.com     nxt_port_enable(task, port, &nxt_main_process_port_handlers);
520240Sigor@sysoev.ru 
521240Sigor@sysoev.ru     process->ready = 1;
522240Sigor@sysoev.ru 
523240Sigor@sysoev.ru     return NXT_OK;
524240Sigor@sysoev.ru }
525240Sigor@sysoev.ru 
526240Sigor@sysoev.ru 
527240Sigor@sysoev.ru static void
528240Sigor@sysoev.ru nxt_main_process_title(nxt_task_t *task)
529240Sigor@sysoev.ru {
530240Sigor@sysoev.ru     u_char      *p, *end;
531240Sigor@sysoev.ru     nxt_uint_t  i;
532240Sigor@sysoev.ru     u_char      title[2048];
533240Sigor@sysoev.ru 
534240Sigor@sysoev.ru     end = title + sizeof(title) - 1;
535240Sigor@sysoev.ru 
536680Sigor@sysoev.ru     p = nxt_sprintf(title, end, "unit: main v" NXT_VERSION " [%s",
537680Sigor@sysoev.ru                     nxt_process_argv[0]);
538240Sigor@sysoev.ru 
539240Sigor@sysoev.ru     for (i = 1; nxt_process_argv[i] != NULL; i++) {
540240Sigor@sysoev.ru         p = nxt_sprintf(p, end, " %s", nxt_process_argv[i]);
541240Sigor@sysoev.ru     }
542240Sigor@sysoev.ru 
543240Sigor@sysoev.ru     if (p < end) {
544240Sigor@sysoev.ru         *p++ = ']';
545240Sigor@sysoev.ru     }
546240Sigor@sysoev.ru 
547240Sigor@sysoev.ru     *p = '\0';
548240Sigor@sysoev.ru 
549240Sigor@sysoev.ru     nxt_process_title(task, "%s", title);
550240Sigor@sysoev.ru }
551240Sigor@sysoev.ru 
552240Sigor@sysoev.ru 
553240Sigor@sysoev.ru static nxt_int_t
554240Sigor@sysoev.ru nxt_main_start_controller_process(nxt_task_t *task, nxt_runtime_t *rt)
555240Sigor@sysoev.ru {
556240Sigor@sysoev.ru     nxt_process_init_t  *init;
557240Sigor@sysoev.ru 
5581302St.nateldemoura@f5.com     static const nxt_str_t  name = nxt_string("controller");
5591302St.nateldemoura@f5.com 
5601302St.nateldemoura@f5.com     init = nxt_process_init_create(task, NXT_PROCESS_CONTROLLER, &name);
561368Svbart@nginx.com     if (nxt_slow_path(init == NULL)) {
562368Svbart@nginx.com         return NXT_ERROR;
563368Svbart@nginx.com     }
564368Svbart@nginx.com 
565368Svbart@nginx.com     return nxt_main_create_controller_process(task, rt, init);;
566368Svbart@nginx.com }
567368Svbart@nginx.com 
568368Svbart@nginx.com 
569368Svbart@nginx.com static nxt_int_t
570368Svbart@nginx.com nxt_main_create_controller_process(nxt_task_t *task, nxt_runtime_t *rt,
571368Svbart@nginx.com     nxt_process_init_t *init)
572368Svbart@nginx.com {
573774Svbart@nginx.com     ssize_t                n;
574774Svbart@nginx.com     nxt_int_t              ret;
575774Svbart@nginx.com     nxt_str_t              *conf;
576774Svbart@nginx.com     nxt_file_t             file;
577774Svbart@nginx.com     nxt_file_info_t        fi;
578774Svbart@nginx.com     nxt_controller_init_t  ctrl_init;
579368Svbart@nginx.com 
580774Svbart@nginx.com     nxt_memzero(&ctrl_init, sizeof(nxt_controller_init_t));
581774Svbart@nginx.com 
582774Svbart@nginx.com     conf = &ctrl_init.conf;
583314Svbart@nginx.com 
584314Svbart@nginx.com     nxt_memzero(&file, sizeof(nxt_file_t));
585314Svbart@nginx.com 
586314Svbart@nginx.com     file.name = (nxt_file_name_t *) rt->conf;
587314Svbart@nginx.com 
588329Sigor@sysoev.ru     ret = nxt_file_open(task, &file, NXT_FILE_RDONLY, NXT_FILE_OPEN, 0);
589314Svbart@nginx.com 
590329Sigor@sysoev.ru     if (ret == NXT_OK) {
591329Sigor@sysoev.ru         ret = nxt_file_info(&file, &fi);
592329Sigor@sysoev.ru 
593329Sigor@sysoev.ru         if (nxt_fast_path(ret == NXT_OK && nxt_is_file(&fi))) {
594774Svbart@nginx.com             conf->length = nxt_file_size(&fi);
595774Svbart@nginx.com             conf->start = nxt_malloc(conf->length);
596314Svbart@nginx.com 
597774Svbart@nginx.com             if (nxt_slow_path(conf->start == NULL)) {
598314Svbart@nginx.com                 nxt_file_close(task, &file);
599314Svbart@nginx.com                 return NXT_ERROR;
600314Svbart@nginx.com             }
601314Svbart@nginx.com 
602774Svbart@nginx.com             n = nxt_file_read(&file, conf->start, conf->length, 0);
603314Svbart@nginx.com 
604774Svbart@nginx.com             if (nxt_slow_path(n != (ssize_t) conf->length)) {
605774Svbart@nginx.com                 nxt_free(conf->start);
606774Svbart@nginx.com                 conf->start = NULL;
607314Svbart@nginx.com 
608564Svbart@nginx.com                 nxt_alert(task, "failed to restore previous configuration: "
609564Svbart@nginx.com                           "cannot read the file");
610314Svbart@nginx.com             }
611314Svbart@nginx.com         }
612314Svbart@nginx.com 
613314Svbart@nginx.com         nxt_file_close(task, &file);
614314Svbart@nginx.com     }
615314Svbart@nginx.com 
616774Svbart@nginx.com #if (NXT_TLS)
617774Svbart@nginx.com     ctrl_init.certs = nxt_cert_store_load(task);
618774Svbart@nginx.com #endif
619774Svbart@nginx.com 
620774Svbart@nginx.com     init->data = &ctrl_init;
621240Sigor@sysoev.ru 
622314Svbart@nginx.com     ret = nxt_main_create_worker_process(task, rt, init);
623314Svbart@nginx.com 
624774Svbart@nginx.com     if (ret == NXT_OK) {
625774Svbart@nginx.com         if (conf->start != NULL) {
626774Svbart@nginx.com             nxt_free(conf->start);
627774Svbart@nginx.com         }
628774Svbart@nginx.com 
629774Svbart@nginx.com #if (NXT_TLS)
630774Svbart@nginx.com         if (ctrl_init.certs != NULL) {
631774Svbart@nginx.com             nxt_cert_store_release(ctrl_init.certs);
632774Svbart@nginx.com         }
633774Svbart@nginx.com #endif
634314Svbart@nginx.com     }
635314Svbart@nginx.com 
636314Svbart@nginx.com     return ret;
637240Sigor@sysoev.ru }
638240Sigor@sysoev.ru 
639240Sigor@sysoev.ru 
640240Sigor@sysoev.ru static nxt_int_t
641240Sigor@sysoev.ru nxt_main_start_discovery_process(nxt_task_t *task, nxt_runtime_t *rt)
642240Sigor@sysoev.ru {
643240Sigor@sysoev.ru     nxt_process_init_t  *init;
644240Sigor@sysoev.ru 
6451302St.nateldemoura@f5.com     static const nxt_str_t  name = nxt_string("discovery");
6461302St.nateldemoura@f5.com 
6471302St.nateldemoura@f5.com     init = nxt_process_init_create(task, NXT_PROCESS_DISCOVERY, &name);
648240Sigor@sysoev.ru     if (nxt_slow_path(init == NULL)) {
649240Sigor@sysoev.ru         return NXT_ERROR;
650240Sigor@sysoev.ru     }
651240Sigor@sysoev.ru 
652240Sigor@sysoev.ru     return nxt_main_create_worker_process(task, rt, init);
653240Sigor@sysoev.ru }
654240Sigor@sysoev.ru 
655240Sigor@sysoev.ru 
656240Sigor@sysoev.ru static nxt_int_t
657240Sigor@sysoev.ru nxt_main_start_router_process(nxt_task_t *task, nxt_runtime_t *rt)
658240Sigor@sysoev.ru {
659240Sigor@sysoev.ru     nxt_process_init_t  *init;
660240Sigor@sysoev.ru 
6611302St.nateldemoura@f5.com     static const nxt_str_t  name = nxt_string("router");
6621302St.nateldemoura@f5.com 
6631302St.nateldemoura@f5.com     init = nxt_process_init_create(task, NXT_PROCESS_ROUTER, &name);
664240Sigor@sysoev.ru     if (nxt_slow_path(init == NULL)) {
665240Sigor@sysoev.ru         return NXT_ERROR;
666240Sigor@sysoev.ru     }
667240Sigor@sysoev.ru 
6681302St.nateldemoura@f5.com     return nxt_main_create_router_process(task, rt, init);
6691302St.nateldemoura@f5.com }
6701302St.nateldemoura@f5.com 
6711302St.nateldemoura@f5.com 
6721302St.nateldemoura@f5.com static nxt_int_t
6731302St.nateldemoura@f5.com nxt_main_create_router_process(nxt_task_t *task, nxt_runtime_t *rt,
6741302St.nateldemoura@f5.com     nxt_process_init_t *init)
6751302St.nateldemoura@f5.com {
6761302St.nateldemoura@f5.com     nxt_main_stop_worker_processes(task, rt);
677240Sigor@sysoev.ru 
678240Sigor@sysoev.ru     return nxt_main_create_worker_process(task, rt, init);
679240Sigor@sysoev.ru }
680240Sigor@sysoev.ru 
6811302St.nateldemoura@f5.com 
682240Sigor@sysoev.ru static nxt_int_t
683240Sigor@sysoev.ru nxt_main_start_worker_process(nxt_task_t *task, nxt_runtime_t *rt,
684240Sigor@sysoev.ru     nxt_common_app_conf_t *app_conf, uint32_t stream)
685240Sigor@sysoev.ru {
6861306St.nateldemoura@f5.com     nxt_int_t           cap_setid;
6871182St.nateldemoura@f5.com     nxt_int_t           ret;
688240Sigor@sysoev.ru     nxt_process_init_t  *init;
689240Sigor@sysoev.ru 
6901302St.nateldemoura@f5.com     init = nxt_process_init_create(task, NXT_PROCESS_WORKER, &app_conf->name);
691240Sigor@sysoev.ru     if (nxt_slow_path(init == NULL)) {
692240Sigor@sysoev.ru         return NXT_ERROR;
693240Sigor@sysoev.ru     }
694240Sigor@sysoev.ru 
6951306St.nateldemoura@f5.com     cap_setid = rt->capabilities.setid;
6961306St.nateldemoura@f5.com 
6971306St.nateldemoura@f5.com     if (app_conf->isolation != NULL) {
6981306St.nateldemoura@f5.com         ret = nxt_init_isolation(task, app_conf->isolation, init);
6991306St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
7001306St.nateldemoura@f5.com             goto fail;
7011306St.nateldemoura@f5.com         }
7021306St.nateldemoura@f5.com     }
7031306St.nateldemoura@f5.com 
7041306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER)
7051306St.nateldemoura@f5.com     if (NXT_CLONE_USER(init->isolation.clone.flags)) {
7061306St.nateldemoura@f5.com         cap_setid = 1;
7071306St.nateldemoura@f5.com     }
7081306St.nateldemoura@f5.com #endif
7091306St.nateldemoura@f5.com 
7101306St.nateldemoura@f5.com     if (cap_setid) {
7111302St.nateldemoura@f5.com         ret = nxt_process_init_creds_set(task, init, &app_conf->user,
7121302St.nateldemoura@f5.com                                          &app_conf->group);
7131302St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
7141202St.nateldemoura@f5.com             goto fail;
7151182St.nateldemoura@f5.com         }
7161182St.nateldemoura@f5.com 
717240Sigor@sysoev.ru     } else {
7181182St.nateldemoura@f5.com         if (!nxt_str_eq(&app_conf->user, (u_char *) rt->user_cred.user,
7191182St.nateldemoura@f5.com                         nxt_strlen(rt->user_cred.user)))
7201182St.nateldemoura@f5.com         {
7211182St.nateldemoura@f5.com             nxt_alert(task, "cannot set user \"%V\" for app \"%V\": "
7221182St.nateldemoura@f5.com                       "missing capabilities", &app_conf->user, &app_conf->name);
7231202St.nateldemoura@f5.com             goto fail;
7241182St.nateldemoura@f5.com         }
725240Sigor@sysoev.ru 
7261182St.nateldemoura@f5.com         if (app_conf->group.length > 0
7271182St.nateldemoura@f5.com             && !nxt_str_eq(&app_conf->group, (u_char *) rt->group,
7281182St.nateldemoura@f5.com                            nxt_strlen(rt->group)))
7291182St.nateldemoura@f5.com         {
7301182St.nateldemoura@f5.com             nxt_alert(task, "cannot set group \"%V\" for app \"%V\": "
7311182St.nateldemoura@f5.com                             "missing capabilities", &app_conf->group,
7321182St.nateldemoura@f5.com                             &app_conf->name);
7331202St.nateldemoura@f5.com             goto fail;
7341182St.nateldemoura@f5.com         }
735240Sigor@sysoev.ru     }
736240Sigor@sysoev.ru 
737240Sigor@sysoev.ru     init->data = app_conf;
738240Sigor@sysoev.ru     init->stream = stream;
739240Sigor@sysoev.ru 
7401306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER)
7411306St.nateldemoura@f5.com     ret = nxt_init_vldt_isolation_creds(task, init);
7421182St.nateldemoura@f5.com     if (nxt_slow_path(ret != NXT_OK)) {
7431202St.nateldemoura@f5.com         goto fail;
7441182St.nateldemoura@f5.com     }
7451306St.nateldemoura@f5.com #endif
7461182St.nateldemoura@f5.com 
747240Sigor@sysoev.ru     return nxt_main_create_worker_process(task, rt, init);
7481202St.nateldemoura@f5.com 
7491202St.nateldemoura@f5.com fail:
7501202St.nateldemoura@f5.com 
7511302St.nateldemoura@f5.com     nxt_mp_destroy(init->mem_pool);
7521202St.nateldemoura@f5.com 
7531202St.nateldemoura@f5.com     return NXT_ERROR;
754240Sigor@sysoev.ru }
755240Sigor@sysoev.ru 
756240Sigor@sysoev.ru 
7571302St.nateldemoura@f5.com nxt_int_t
758240Sigor@sysoev.ru nxt_main_create_worker_process(nxt_task_t *task, nxt_runtime_t *rt,
759240Sigor@sysoev.ru     nxt_process_init_t *init)
760240Sigor@sysoev.ru {
761240Sigor@sysoev.ru     nxt_int_t      ret;
762240Sigor@sysoev.ru     nxt_pid_t      pid;
763240Sigor@sysoev.ru     nxt_port_t     *port;
764240Sigor@sysoev.ru     nxt_process_t  *process;
765240Sigor@sysoev.ru 
766240Sigor@sysoev.ru     /*
767240Sigor@sysoev.ru      * TODO: remove process, init, ports from array on memory and fork failures.
768240Sigor@sysoev.ru      */
769240Sigor@sysoev.ru 
770240Sigor@sysoev.ru     process = nxt_runtime_process_new(rt);
771240Sigor@sysoev.ru     if (nxt_slow_path(process == NULL)) {
7721302St.nateldemoura@f5.com         nxt_mp_destroy(init->mem_pool);
7731253Smax.romanov@nginx.com 
774240Sigor@sysoev.ru         return NXT_ERROR;
775240Sigor@sysoev.ru     }
776240Sigor@sysoev.ru 
777240Sigor@sysoev.ru     process->init = init;
778240Sigor@sysoev.ru 
779240Sigor@sysoev.ru     port = nxt_port_new(task, 0, 0, init->type);
780240Sigor@sysoev.ru     if (nxt_slow_path(port == NULL)) {
781349Smax.romanov@nginx.com         nxt_process_use(task, process, -1);
782240Sigor@sysoev.ru         return NXT_ERROR;
783240Sigor@sysoev.ru     }
784240Sigor@sysoev.ru 
785240Sigor@sysoev.ru     nxt_process_port_add(task, process, port);
786240Sigor@sysoev.ru 
787349Smax.romanov@nginx.com     nxt_process_use(task, process, -1);
788349Smax.romanov@nginx.com 
789240Sigor@sysoev.ru     ret = nxt_port_socket_init(task, port, 0);
790240Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
791343Smax.romanov@nginx.com         nxt_port_use(task, port, -1);
792240Sigor@sysoev.ru         return ret;
793240Sigor@sysoev.ru     }
794240Sigor@sysoev.ru 
795240Sigor@sysoev.ru     pid = nxt_process_create(task, process);
796240Sigor@sysoev.ru 
797240Sigor@sysoev.ru     switch (pid) {
798240Sigor@sysoev.ru 
799240Sigor@sysoev.ru     case -1:
8001180Smax.romanov@nginx.com         nxt_port_close(task, port);
8011180Smax.romanov@nginx.com         nxt_port_use(task, port, -1);
8021180Smax.romanov@nginx.com 
803240Sigor@sysoev.ru         return NXT_ERROR;
804240Sigor@sysoev.ru 
805240Sigor@sysoev.ru     case 0:
806240Sigor@sysoev.ru         /* A worker process, return to the event engine work queue loop. */
8071180Smax.romanov@nginx.com         nxt_port_use(task, port, -1);
8081180Smax.romanov@nginx.com 
809240Sigor@sysoev.ru         return NXT_AGAIN;
810240Sigor@sysoev.ru 
811240Sigor@sysoev.ru     default:
812240Sigor@sysoev.ru         /* The main process created a new process. */
813240Sigor@sysoev.ru 
814240Sigor@sysoev.ru         nxt_port_read_close(port);
815240Sigor@sysoev.ru         nxt_port_write_enable(task, port);
816240Sigor@sysoev.ru 
8171180Smax.romanov@nginx.com         nxt_port_use(task, port, -1);
8181180Smax.romanov@nginx.com 
819240Sigor@sysoev.ru         return NXT_OK;
820240Sigor@sysoev.ru     }
821240Sigor@sysoev.ru }
822240Sigor@sysoev.ru 
823240Sigor@sysoev.ru 
824240Sigor@sysoev.ru void
825754Smax.romanov@nginx.com nxt_main_stop_all_processes(nxt_task_t *task, nxt_runtime_t *rt)
826240Sigor@sysoev.ru {
827240Sigor@sysoev.ru     nxt_port_t     *port;
828240Sigor@sysoev.ru     nxt_process_t  *process;
829240Sigor@sysoev.ru 
830277Sigor@sysoev.ru     nxt_runtime_process_each(rt, process) {
831277Sigor@sysoev.ru 
832240Sigor@sysoev.ru         if (nxt_pid != process->pid) {
833240Sigor@sysoev.ru             nxt_process_port_each(process, port) {
834240Sigor@sysoev.ru 
835240Sigor@sysoev.ru                 (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT,
836240Sigor@sysoev.ru                                              -1, 0, 0, NULL);
837240Sigor@sysoev.ru 
838240Sigor@sysoev.ru             } nxt_process_port_loop;
839240Sigor@sysoev.ru         }
840277Sigor@sysoev.ru 
841277Sigor@sysoev.ru     } nxt_runtime_process_loop;
842240Sigor@sysoev.ru }
843240Sigor@sysoev.ru 
844240Sigor@sysoev.ru 
845240Sigor@sysoev.ru 
846240Sigor@sysoev.ru static void
847240Sigor@sysoev.ru nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, void *data)
848240Sigor@sysoev.ru {
849240Sigor@sysoev.ru     nxt_debug(task, "sigterm handler signo:%d (%s)",
850240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
851240Sigor@sysoev.ru 
852240Sigor@sysoev.ru     /* TODO: fast exit. */
853240Sigor@sysoev.ru 
854240Sigor@sysoev.ru     nxt_exiting = 1;
855240Sigor@sysoev.ru 
856697Sigor@sysoev.ru     nxt_runtime_quit(task, 0);
857240Sigor@sysoev.ru }
858240Sigor@sysoev.ru 
859240Sigor@sysoev.ru 
860240Sigor@sysoev.ru static void
861240Sigor@sysoev.ru nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, void *data)
862240Sigor@sysoev.ru {
863240Sigor@sysoev.ru     nxt_debug(task, "sigquit handler signo:%d (%s)",
864240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
865240Sigor@sysoev.ru 
866240Sigor@sysoev.ru     /* TODO: graceful exit. */
867240Sigor@sysoev.ru 
868240Sigor@sysoev.ru     nxt_exiting = 1;
869240Sigor@sysoev.ru 
870697Sigor@sysoev.ru     nxt_runtime_quit(task, 0);
871240Sigor@sysoev.ru }
872240Sigor@sysoev.ru 
873240Sigor@sysoev.ru 
874240Sigor@sysoev.ru static void
875240Sigor@sysoev.ru nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, void *data)
876240Sigor@sysoev.ru {
877240Sigor@sysoev.ru     nxt_mp_t        *mp;
878240Sigor@sysoev.ru     nxt_int_t       ret;
879240Sigor@sysoev.ru     nxt_uint_t      n;
880631Svbart@nginx.com     nxt_port_t      *port;
881240Sigor@sysoev.ru     nxt_file_t      *file, *new_file;
882631Svbart@nginx.com     nxt_array_t     *new_files;
883240Sigor@sysoev.ru     nxt_runtime_t   *rt;
884240Sigor@sysoev.ru 
885240Sigor@sysoev.ru     nxt_log(task, NXT_LOG_NOTICE, "signal %d (%s) recevied, %s",
886240Sigor@sysoev.ru             (int) (uintptr_t) obj, data, "log files rotation");
887240Sigor@sysoev.ru 
888631Svbart@nginx.com     rt = task->thread->runtime;
889631Svbart@nginx.com 
890631Svbart@nginx.com     port = rt->port_by_type[NXT_PROCESS_ROUTER];
891631Svbart@nginx.com 
892631Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
893631Svbart@nginx.com         (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_ACCESS_LOG,
894631Svbart@nginx.com                                      -1, 0, 0, NULL);
895631Svbart@nginx.com     }
896631Svbart@nginx.com 
897240Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
898240Sigor@sysoev.ru     if (mp == NULL) {
899240Sigor@sysoev.ru         return;
900240Sigor@sysoev.ru     }
901240Sigor@sysoev.ru 
902240Sigor@sysoev.ru     n = nxt_list_nelts(rt->log_files);
903240Sigor@sysoev.ru 
904240Sigor@sysoev.ru     new_files = nxt_array_create(mp, n, sizeof(nxt_file_t));
905240Sigor@sysoev.ru     if (new_files == NULL) {
906240Sigor@sysoev.ru         nxt_mp_destroy(mp);
907240Sigor@sysoev.ru         return;
908240Sigor@sysoev.ru     }
909240Sigor@sysoev.ru 
910240Sigor@sysoev.ru     nxt_list_each(file, rt->log_files) {
911240Sigor@sysoev.ru 
912240Sigor@sysoev.ru         /* This allocation cannot fail. */
913240Sigor@sysoev.ru         new_file = nxt_array_add(new_files);
914240Sigor@sysoev.ru 
915240Sigor@sysoev.ru         new_file->name = file->name;
916240Sigor@sysoev.ru         new_file->fd = NXT_FILE_INVALID;
917564Svbart@nginx.com         new_file->log_level = NXT_LOG_ALERT;
918240Sigor@sysoev.ru 
919240Sigor@sysoev.ru         ret = nxt_file_open(task, new_file, O_WRONLY | O_APPEND, O_CREAT,
920240Sigor@sysoev.ru                             NXT_FILE_OWNER_ACCESS);
921240Sigor@sysoev.ru 
922240Sigor@sysoev.ru         if (ret != NXT_OK) {
923240Sigor@sysoev.ru             goto fail;
924240Sigor@sysoev.ru         }
925240Sigor@sysoev.ru 
926240Sigor@sysoev.ru     } nxt_list_loop;
927240Sigor@sysoev.ru 
928240Sigor@sysoev.ru     new_file = new_files->elts;
929240Sigor@sysoev.ru 
930240Sigor@sysoev.ru     ret = nxt_file_stderr(&new_file[0]);
931240Sigor@sysoev.ru 
932240Sigor@sysoev.ru     if (ret == NXT_OK) {
933240Sigor@sysoev.ru         n = 0;
934240Sigor@sysoev.ru 
935240Sigor@sysoev.ru         nxt_list_each(file, rt->log_files) {
936240Sigor@sysoev.ru 
937240Sigor@sysoev.ru             nxt_port_change_log_file(task, rt, n, new_file[n].fd);
938240Sigor@sysoev.ru             /*
939240Sigor@sysoev.ru              * The old log file descriptor must be closed at the moment
940240Sigor@sysoev.ru              * when no other threads use it.  dup2() allows to use the
941240Sigor@sysoev.ru              * old file descriptor for new log file.  This change is
942240Sigor@sysoev.ru              * performed atomically in the kernel.
943240Sigor@sysoev.ru              */
944240Sigor@sysoev.ru             (void) nxt_file_redirect(file, new_file[n].fd);
945240Sigor@sysoev.ru 
946240Sigor@sysoev.ru             n++;
947240Sigor@sysoev.ru 
948240Sigor@sysoev.ru         } nxt_list_loop;
949240Sigor@sysoev.ru 
950240Sigor@sysoev.ru         nxt_mp_destroy(mp);
951240Sigor@sysoev.ru         return;
9521008Szelenkov@nginx.com     }
953240Sigor@sysoev.ru 
954240Sigor@sysoev.ru fail:
955240Sigor@sysoev.ru 
956240Sigor@sysoev.ru     new_file = new_files->elts;
957240Sigor@sysoev.ru     n = new_files->nelts;
958240Sigor@sysoev.ru 
959240Sigor@sysoev.ru     while (n != 0) {
960240Sigor@sysoev.ru         if (new_file->fd != NXT_FILE_INVALID) {
961240Sigor@sysoev.ru             nxt_file_close(task, new_file);
962240Sigor@sysoev.ru         }
963240Sigor@sysoev.ru 
964240Sigor@sysoev.ru         new_file++;
965240Sigor@sysoev.ru         n--;
966240Sigor@sysoev.ru     }
967240Sigor@sysoev.ru 
968240Sigor@sysoev.ru     nxt_mp_destroy(mp);
969240Sigor@sysoev.ru }
970240Sigor@sysoev.ru 
971240Sigor@sysoev.ru 
972240Sigor@sysoev.ru static void
973240Sigor@sysoev.ru nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, void *data)
974240Sigor@sysoev.ru {
975240Sigor@sysoev.ru     int                    status;
976240Sigor@sysoev.ru     nxt_err_t              err;
977240Sigor@sysoev.ru     nxt_pid_t              pid;
978240Sigor@sysoev.ru 
979240Sigor@sysoev.ru     nxt_debug(task, "sigchld handler signo:%d (%s)",
980240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
981240Sigor@sysoev.ru 
982240Sigor@sysoev.ru     for ( ;; ) {
983240Sigor@sysoev.ru         pid = waitpid(-1, &status, WNOHANG);
984240Sigor@sysoev.ru 
985240Sigor@sysoev.ru         if (pid == -1) {
986240Sigor@sysoev.ru 
987240Sigor@sysoev.ru             switch (err = nxt_errno) {
988240Sigor@sysoev.ru 
989240Sigor@sysoev.ru             case NXT_ECHILD:
990240Sigor@sysoev.ru                 return;
991240Sigor@sysoev.ru 
992240Sigor@sysoev.ru             case NXT_EINTR:
993240Sigor@sysoev.ru                 continue;
994240Sigor@sysoev.ru 
995240Sigor@sysoev.ru             default:
996564Svbart@nginx.com                 nxt_alert(task, "waitpid() failed: %E", err);
997240Sigor@sysoev.ru                 return;
998240Sigor@sysoev.ru             }
999240Sigor@sysoev.ru         }
1000240Sigor@sysoev.ru 
1001240Sigor@sysoev.ru         nxt_debug(task, "waitpid(): %PI", pid);
1002240Sigor@sysoev.ru 
1003240Sigor@sysoev.ru         if (pid == 0) {
1004240Sigor@sysoev.ru             return;
1005240Sigor@sysoev.ru         }
1006240Sigor@sysoev.ru 
1007240Sigor@sysoev.ru         if (WTERMSIG(status)) {
1008240Sigor@sysoev.ru #ifdef WCOREDUMP
1009564Svbart@nginx.com             nxt_alert(task, "process %PI exited on signal %d%s",
1010564Svbart@nginx.com                       pid, WTERMSIG(status),
1011564Svbart@nginx.com                       WCOREDUMP(status) ? " (core dumped)" : "");
1012240Sigor@sysoev.ru #else
1013564Svbart@nginx.com             nxt_alert(task, "process %PI exited on signal %d",
1014564Svbart@nginx.com                       pid, WTERMSIG(status));
1015240Sigor@sysoev.ru #endif
1016240Sigor@sysoev.ru 
1017240Sigor@sysoev.ru         } else {
1018240Sigor@sysoev.ru             nxt_trace(task, "process %PI exited with code %d",
1019240Sigor@sysoev.ru                       pid, WEXITSTATUS(status));
1020240Sigor@sysoev.ru         }
1021240Sigor@sysoev.ru 
1022240Sigor@sysoev.ru         nxt_main_cleanup_worker_process(task, pid);
1023240Sigor@sysoev.ru     }
1024240Sigor@sysoev.ru }
1025240Sigor@sysoev.ru 
1026240Sigor@sysoev.ru 
1027240Sigor@sysoev.ru static void
1028944Sigor@sysoev.ru nxt_main_process_signal_handler(nxt_task_t *task, void *obj, void *data)
1029944Sigor@sysoev.ru {
1030944Sigor@sysoev.ru     nxt_trace(task, "signal signo:%d (%s) recevied, ignored",
1031944Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
1032944Sigor@sysoev.ru }
1033944Sigor@sysoev.ru 
1034944Sigor@sysoev.ru 
1035944Sigor@sysoev.ru static void
1036240Sigor@sysoev.ru nxt_main_cleanup_worker_process(nxt_task_t *task, nxt_pid_t pid)
1037240Sigor@sysoev.ru {
10381302St.nateldemoura@f5.com     nxt_buf_t              *buf;
10391302St.nateldemoura@f5.com     nxt_port_t             *port;
10401302St.nateldemoura@f5.com     nxt_runtime_t          *rt;
10411302St.nateldemoura@f5.com     nxt_process_t          *process;
10421302St.nateldemoura@f5.com     nxt_process_type_t     ptype;
10431302St.nateldemoura@f5.com     nxt_process_init_t     *init;
10441302St.nateldemoura@f5.com     nxt_process_restart_t  restart;
1045240Sigor@sysoev.ru 
1046240Sigor@sysoev.ru     rt = task->thread->runtime;
1047240Sigor@sysoev.ru 
1048240Sigor@sysoev.ru     process = nxt_runtime_process_find(rt, pid);
1049240Sigor@sysoev.ru 
1050240Sigor@sysoev.ru     if (process) {
1051240Sigor@sysoev.ru         init = process->init;
10521253Smax.romanov@nginx.com         process->init = NULL;
1053240Sigor@sysoev.ru 
1054366Smax.romanov@nginx.com         ptype = nxt_process_type(process);
10551302St.nateldemoura@f5.com         restart = nxt_process_restarts[ptype];
1056366Smax.romanov@nginx.com 
10571253Smax.romanov@nginx.com         if (process->ready) {
1058782Smax.romanov@nginx.com             init->stream = 0;
1059782Smax.romanov@nginx.com         }
1060782Smax.romanov@nginx.com 
1061349Smax.romanov@nginx.com         nxt_process_close_ports(task, process);
1062240Sigor@sysoev.ru 
1063240Sigor@sysoev.ru         if (nxt_exiting) {
10641302St.nateldemoura@f5.com             nxt_mp_destroy(init->mem_pool);
10651302St.nateldemoura@f5.com 
10661211Smax.romanov@nginx.com             if (rt->nprocesses <= 2) {
1067697Sigor@sysoev.ru                 nxt_runtime_quit(task, 0);
1068240Sigor@sysoev.ru             }
1069240Sigor@sysoev.ru 
10701211Smax.romanov@nginx.com             return;
10711211Smax.romanov@nginx.com         }
10721211Smax.romanov@nginx.com 
10731211Smax.romanov@nginx.com         nxt_runtime_process_each(rt, process) {
10741211Smax.romanov@nginx.com 
10751211Smax.romanov@nginx.com             if (process->pid == nxt_pid
10761211Smax.romanov@nginx.com                 || process->pid == pid
10771211Smax.romanov@nginx.com                 || nxt_queue_is_empty(&process->ports))
10781211Smax.romanov@nginx.com             {
10791211Smax.romanov@nginx.com                 continue;
10801211Smax.romanov@nginx.com             }
10811211Smax.romanov@nginx.com 
10821211Smax.romanov@nginx.com             port = nxt_process_port_first(process);
10831211Smax.romanov@nginx.com 
10841211Smax.romanov@nginx.com             if (nxt_proc_remove_notify_matrix[ptype][port->type] == 0) {
10851211Smax.romanov@nginx.com                 continue;
10861211Smax.romanov@nginx.com             }
1087754Smax.romanov@nginx.com 
10881211Smax.romanov@nginx.com             buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
10891211Smax.romanov@nginx.com                                        sizeof(pid));
10901211Smax.romanov@nginx.com             if (nxt_slow_path(buf == NULL)) {
10911211Smax.romanov@nginx.com                 continue;
10921211Smax.romanov@nginx.com             }
10931211Smax.romanov@nginx.com 
10941211Smax.romanov@nginx.com             buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid));
1095240Sigor@sysoev.ru 
10961211Smax.romanov@nginx.com             nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID,
10971211Smax.romanov@nginx.com                                   -1, init->stream, 0, buf);
10981211Smax.romanov@nginx.com         } nxt_runtime_process_loop;
10991211Smax.romanov@nginx.com 
11001302St.nateldemoura@f5.com         if (restart != NULL) {
11011302St.nateldemoura@f5.com             restart(task, rt, init);
11021211Smax.romanov@nginx.com 
11031211Smax.romanov@nginx.com         } else {
11041302St.nateldemoura@f5.com             nxt_mp_destroy(init->mem_pool);
1105240Sigor@sysoev.ru         }
1106240Sigor@sysoev.ru     }
1107240Sigor@sysoev.ru }
1108240Sigor@sysoev.ru 
1109240Sigor@sysoev.ru 
1110240Sigor@sysoev.ru static void
1111754Smax.romanov@nginx.com nxt_main_stop_worker_processes(nxt_task_t *task, nxt_runtime_t *rt)
1112754Smax.romanov@nginx.com {
1113754Smax.romanov@nginx.com     nxt_port_t     *port;
1114754Smax.romanov@nginx.com     nxt_process_t  *process;
1115754Smax.romanov@nginx.com 
1116754Smax.romanov@nginx.com     nxt_runtime_process_each(rt, process) {
1117754Smax.romanov@nginx.com 
1118754Smax.romanov@nginx.com         nxt_process_port_each(process, port) {
1119754Smax.romanov@nginx.com 
1120754Smax.romanov@nginx.com             if (port->type == NXT_PROCESS_WORKER) {
1121754Smax.romanov@nginx.com                 (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT,
1122754Smax.romanov@nginx.com                                              -1, 0, 0, NULL);
1123754Smax.romanov@nginx.com             }
1124754Smax.romanov@nginx.com 
1125754Smax.romanov@nginx.com         } nxt_process_port_loop;
1126754Smax.romanov@nginx.com 
1127754Smax.romanov@nginx.com     } nxt_runtime_process_loop;
1128754Smax.romanov@nginx.com }
1129754Smax.romanov@nginx.com 
1130754Smax.romanov@nginx.com 
1131754Smax.romanov@nginx.com static void
1132240Sigor@sysoev.ru nxt_main_port_socket_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1133240Sigor@sysoev.ru {
1134240Sigor@sysoev.ru     size_t                  size;
1135240Sigor@sysoev.ru     nxt_int_t               ret;
1136240Sigor@sysoev.ru     nxt_buf_t               *b, *out;
1137240Sigor@sysoev.ru     nxt_port_t              *port;
1138240Sigor@sysoev.ru     nxt_sockaddr_t          *sa;
1139240Sigor@sysoev.ru     nxt_port_msg_type_t     type;
1140240Sigor@sysoev.ru     nxt_listening_socket_t  ls;
1141240Sigor@sysoev.ru     u_char                  message[2048];
1142240Sigor@sysoev.ru 
1143240Sigor@sysoev.ru     b = msg->buf;
1144240Sigor@sysoev.ru     sa = (nxt_sockaddr_t *) b->mem.pos;
1145240Sigor@sysoev.ru 
1146352Smax.romanov@nginx.com     /* TODO check b size and make plain */
1147352Smax.romanov@nginx.com 
1148240Sigor@sysoev.ru     out = NULL;
1149240Sigor@sysoev.ru 
1150240Sigor@sysoev.ru     ls.socket = -1;
1151240Sigor@sysoev.ru     ls.error = NXT_SOCKET_ERROR_SYSTEM;
1152240Sigor@sysoev.ru     ls.start = message;
1153240Sigor@sysoev.ru     ls.end = message + sizeof(message);
1154240Sigor@sysoev.ru 
1155240Sigor@sysoev.ru     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1156240Sigor@sysoev.ru                                  msg->port_msg.reply_port);
1157240Sigor@sysoev.ru 
1158240Sigor@sysoev.ru     nxt_debug(task, "listening socket \"%*s\"",
1159493Spluknet@nginx.com               (size_t) sa->length, nxt_sockaddr_start(sa));
1160240Sigor@sysoev.ru 
1161240Sigor@sysoev.ru     ret = nxt_main_listening_socket(sa, &ls);
1162240Sigor@sysoev.ru 
1163240Sigor@sysoev.ru     if (ret == NXT_OK) {
1164240Sigor@sysoev.ru         nxt_debug(task, "socket(\"%*s\"): %d",
1165493Spluknet@nginx.com                   (size_t) sa->length, nxt_sockaddr_start(sa), ls.socket);
1166240Sigor@sysoev.ru 
1167240Sigor@sysoev.ru         type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD;
1168240Sigor@sysoev.ru 
1169240Sigor@sysoev.ru     } else {
1170240Sigor@sysoev.ru         size = ls.end - ls.start;
1171240Sigor@sysoev.ru 
1172564Svbart@nginx.com         nxt_alert(task, "%*s", size, ls.start);
1173240Sigor@sysoev.ru 
1174342Smax.romanov@nginx.com         out = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
1175342Smax.romanov@nginx.com                                    size + 1);
1176240Sigor@sysoev.ru         if (nxt_slow_path(out == NULL)) {
1177240Sigor@sysoev.ru             return;
1178240Sigor@sysoev.ru         }
1179240Sigor@sysoev.ru 
1180240Sigor@sysoev.ru         *out->mem.free++ = (uint8_t) ls.error;
1181240Sigor@sysoev.ru 
1182240Sigor@sysoev.ru         out->mem.free = nxt_cpymem(out->mem.free, ls.start, size);
1183240Sigor@sysoev.ru 
1184240Sigor@sysoev.ru         type = NXT_PORT_MSG_RPC_ERROR;
1185240Sigor@sysoev.ru     }
1186240Sigor@sysoev.ru 
1187240Sigor@sysoev.ru     nxt_port_socket_write(task, port, type, ls.socket, msg->port_msg.stream,
1188240Sigor@sysoev.ru                           0, out);
1189240Sigor@sysoev.ru }
1190240Sigor@sysoev.ru 
1191240Sigor@sysoev.ru 
1192240Sigor@sysoev.ru static nxt_int_t
1193240Sigor@sysoev.ru nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls)
1194240Sigor@sysoev.ru {
1195240Sigor@sysoev.ru     nxt_err_t         err;
1196240Sigor@sysoev.ru     nxt_socket_t      s;
1197240Sigor@sysoev.ru 
1198240Sigor@sysoev.ru     const socklen_t   length = sizeof(int);
1199240Sigor@sysoev.ru     static const int  enable = 1;
1200240Sigor@sysoev.ru 
1201240Sigor@sysoev.ru     s = socket(sa->u.sockaddr.sa_family, sa->type, 0);
1202240Sigor@sysoev.ru 
1203240Sigor@sysoev.ru     if (nxt_slow_path(s == -1)) {
1204240Sigor@sysoev.ru         err = nxt_errno;
1205240Sigor@sysoev.ru 
1206240Sigor@sysoev.ru #if (NXT_INET6)
1207240Sigor@sysoev.ru 
1208240Sigor@sysoev.ru         if (err == EAFNOSUPPORT && sa->u.sockaddr.sa_family == AF_INET6) {
1209240Sigor@sysoev.ru             ls->error = NXT_SOCKET_ERROR_NOINET6;
1210240Sigor@sysoev.ru         }
1211240Sigor@sysoev.ru 
1212240Sigor@sysoev.ru #endif
1213240Sigor@sysoev.ru 
1214240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end,
1215240Sigor@sysoev.ru                               "socket(\\\"%*s\\\") failed %E",
1216493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa), err);
1217240Sigor@sysoev.ru 
1218240Sigor@sysoev.ru         return NXT_ERROR;
1219240Sigor@sysoev.ru     }
1220240Sigor@sysoev.ru 
1221240Sigor@sysoev.ru     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, length) != 0) {
1222240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end,
1223240Sigor@sysoev.ru                               "setsockopt(\\\"%*s\\\", SO_REUSEADDR) failed %E",
1224493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa),
1225493Spluknet@nginx.com                               nxt_errno);
1226240Sigor@sysoev.ru         goto fail;
1227240Sigor@sysoev.ru     }
1228240Sigor@sysoev.ru 
1229240Sigor@sysoev.ru #if (NXT_INET6)
1230240Sigor@sysoev.ru 
1231240Sigor@sysoev.ru     if (sa->u.sockaddr.sa_family == AF_INET6) {
1232240Sigor@sysoev.ru 
1233240Sigor@sysoev.ru         if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, length) != 0) {
1234240Sigor@sysoev.ru             ls->end = nxt_sprintf(ls->start, ls->end,
1235240Sigor@sysoev.ru                                "setsockopt(\\\"%*s\\\", IPV6_V6ONLY) failed %E",
1236493Spluknet@nginx.com                                (size_t) sa->length, nxt_sockaddr_start(sa),
1237493Spluknet@nginx.com                                nxt_errno);
1238240Sigor@sysoev.ru             goto fail;
1239240Sigor@sysoev.ru         }
1240240Sigor@sysoev.ru     }
1241240Sigor@sysoev.ru 
1242240Sigor@sysoev.ru #endif
1243240Sigor@sysoev.ru 
1244240Sigor@sysoev.ru     if (bind(s, &sa->u.sockaddr, sa->socklen) != 0) {
1245240Sigor@sysoev.ru         err = nxt_errno;
1246240Sigor@sysoev.ru 
1247240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
1248240Sigor@sysoev.ru 
1249240Sigor@sysoev.ru         if (sa->u.sockaddr.sa_family == AF_UNIX) {
1250240Sigor@sysoev.ru             switch (err) {
1251240Sigor@sysoev.ru 
1252240Sigor@sysoev.ru             case EACCES:
1253240Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_ACCESS;
1254240Sigor@sysoev.ru                 break;
1255240Sigor@sysoev.ru 
1256240Sigor@sysoev.ru             case ENOENT:
1257240Sigor@sysoev.ru             case ENOTDIR:
1258240Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_PATH;
1259240Sigor@sysoev.ru                 break;
1260240Sigor@sysoev.ru             }
1261240Sigor@sysoev.ru 
1262908Sigor@sysoev.ru         } else
1263908Sigor@sysoev.ru #endif
1264908Sigor@sysoev.ru         {
1265908Sigor@sysoev.ru             switch (err) {
1266240Sigor@sysoev.ru 
1267908Sigor@sysoev.ru             case EACCES:
1268908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_PORT;
1269908Sigor@sysoev.ru                 break;
1270240Sigor@sysoev.ru 
1271908Sigor@sysoev.ru             case EADDRINUSE:
1272908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_INUSE;
1273908Sigor@sysoev.ru                 break;
1274240Sigor@sysoev.ru 
1275908Sigor@sysoev.ru             case EADDRNOTAVAIL:
1276908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_NOADDR;
1277908Sigor@sysoev.ru                 break;
1278908Sigor@sysoev.ru             }
1279240Sigor@sysoev.ru         }
1280240Sigor@sysoev.ru 
1281240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end, "bind(\\\"%*s\\\") failed %E",
1282493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa), err);
1283240Sigor@sysoev.ru         goto fail;
1284240Sigor@sysoev.ru     }
1285240Sigor@sysoev.ru 
1286240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
1287240Sigor@sysoev.ru 
1288240Sigor@sysoev.ru     if (sa->u.sockaddr.sa_family == AF_UNIX) {
1289240Sigor@sysoev.ru         char     *filename;
1290240Sigor@sysoev.ru         mode_t   access;
1291240Sigor@sysoev.ru 
1292240Sigor@sysoev.ru         filename = sa->u.sockaddr_un.sun_path;
1293240Sigor@sysoev.ru         access = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1294240Sigor@sysoev.ru 
1295240Sigor@sysoev.ru         if (chmod(filename, access) != 0) {
1296240Sigor@sysoev.ru             ls->end = nxt_sprintf(ls->start, ls->end,
1297494Spluknet@nginx.com                                   "chmod(\\\"%s\\\") failed %E",
1298240Sigor@sysoev.ru                                   filename, nxt_errno);
1299240Sigor@sysoev.ru             goto fail;
1300240Sigor@sysoev.ru         }
1301240Sigor@sysoev.ru     }
1302240Sigor@sysoev.ru 
1303240Sigor@sysoev.ru #endif
1304240Sigor@sysoev.ru 
1305240Sigor@sysoev.ru     ls->socket = s;
1306240Sigor@sysoev.ru 
1307240Sigor@sysoev.ru     return NXT_OK;
1308240Sigor@sysoev.ru 
1309240Sigor@sysoev.ru fail:
1310240Sigor@sysoev.ru 
1311240Sigor@sysoev.ru     (void) close(s);
1312240Sigor@sysoev.ru 
1313240Sigor@sysoev.ru     return NXT_ERROR;
1314240Sigor@sysoev.ru }
1315240Sigor@sysoev.ru 
1316240Sigor@sysoev.ru 
1317240Sigor@sysoev.ru static nxt_conf_map_t  nxt_app_lang_module_map[] = {
1318240Sigor@sysoev.ru     {
1319240Sigor@sysoev.ru         nxt_string("type"),
1320356Svbart@nginx.com         NXT_CONF_MAP_INT,
1321240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, type),
1322240Sigor@sysoev.ru     },
1323240Sigor@sysoev.ru 
1324240Sigor@sysoev.ru     {
1325240Sigor@sysoev.ru         nxt_string("version"),
1326354Svbart@nginx.com         NXT_CONF_MAP_CSTRZ,
1327240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, version),
1328240Sigor@sysoev.ru     },
1329240Sigor@sysoev.ru 
1330240Sigor@sysoev.ru     {
1331240Sigor@sysoev.ru         nxt_string("file"),
1332240Sigor@sysoev.ru         NXT_CONF_MAP_CSTRZ,
1333240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, file),
1334240Sigor@sysoev.ru     },
1335240Sigor@sysoev.ru };
1336240Sigor@sysoev.ru 
1337240Sigor@sysoev.ru 
1338240Sigor@sysoev.ru static void
1339240Sigor@sysoev.ru nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1340240Sigor@sysoev.ru {
1341240Sigor@sysoev.ru     uint32_t               index;
1342240Sigor@sysoev.ru     nxt_mp_t               *mp;
1343240Sigor@sysoev.ru     nxt_int_t              ret;
1344240Sigor@sysoev.ru     nxt_buf_t              *b;
1345549Svbart@nginx.com     nxt_port_t             *port;
1346240Sigor@sysoev.ru     nxt_runtime_t          *rt;
1347240Sigor@sysoev.ru     nxt_conf_value_t       *conf, *root, *value;
1348240Sigor@sysoev.ru     nxt_app_lang_module_t  *lang;
1349240Sigor@sysoev.ru 
13501182St.nateldemoura@f5.com     static nxt_str_t root_path = nxt_string("/");
1351240Sigor@sysoev.ru 
1352240Sigor@sysoev.ru     rt = task->thread->runtime;
1353240Sigor@sysoev.ru 
1354240Sigor@sysoev.ru     if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) {
1355240Sigor@sysoev.ru         return;
1356240Sigor@sysoev.ru     }
1357240Sigor@sysoev.ru 
13581211Smax.romanov@nginx.com     if (nxt_exiting) {
13591211Smax.romanov@nginx.com         nxt_debug(task, "ignoring discovered modules, exiting");
13601211Smax.romanov@nginx.com         return;
13611211Smax.romanov@nginx.com     }
13621211Smax.romanov@nginx.com 
1363549Svbart@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1364549Svbart@nginx.com                                  msg->port_msg.reply_port);
1365549Svbart@nginx.com 
1366549Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
1367549Svbart@nginx.com         (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1,
1368549Svbart@nginx.com                                      msg->port_msg.stream, 0, NULL);
1369549Svbart@nginx.com     }
1370549Svbart@nginx.com 
1371240Sigor@sysoev.ru     b = msg->buf;
1372240Sigor@sysoev.ru 
1373240Sigor@sysoev.ru     if (b == NULL) {
1374240Sigor@sysoev.ru         return;
1375240Sigor@sysoev.ru     }
1376240Sigor@sysoev.ru 
1377240Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
1378240Sigor@sysoev.ru     if (mp == NULL) {
1379240Sigor@sysoev.ru         return;
1380240Sigor@sysoev.ru     }
1381240Sigor@sysoev.ru 
1382352Smax.romanov@nginx.com     b = nxt_buf_chk_make_plain(mp, b, msg->size);
1383352Smax.romanov@nginx.com 
1384352Smax.romanov@nginx.com     if (b == NULL) {
1385352Smax.romanov@nginx.com         return;
1386352Smax.romanov@nginx.com     }
1387352Smax.romanov@nginx.com 
1388352Smax.romanov@nginx.com     nxt_debug(task, "application languages: \"%*s\"",
1389352Smax.romanov@nginx.com               b->mem.free - b->mem.pos, b->mem.pos);
1390352Smax.romanov@nginx.com 
1391240Sigor@sysoev.ru     conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL);
1392240Sigor@sysoev.ru     if (conf == NULL) {
1393240Sigor@sysoev.ru         goto fail;
1394240Sigor@sysoev.ru     }
1395240Sigor@sysoev.ru 
1396240Sigor@sysoev.ru     root = nxt_conf_get_path(conf, &root_path);
1397240Sigor@sysoev.ru     if (root == NULL) {
1398240Sigor@sysoev.ru         goto fail;
1399240Sigor@sysoev.ru     }
1400240Sigor@sysoev.ru 
1401240Sigor@sysoev.ru     for (index = 0; /* void */ ; index++) {
1402240Sigor@sysoev.ru         value = nxt_conf_get_array_element(root, index);
1403240Sigor@sysoev.ru         if (value == NULL) {
1404240Sigor@sysoev.ru             break;
1405240Sigor@sysoev.ru         }
1406240Sigor@sysoev.ru 
1407240Sigor@sysoev.ru         lang = nxt_array_add(rt->languages);
1408240Sigor@sysoev.ru         if (lang == NULL) {
1409240Sigor@sysoev.ru             goto fail;
1410240Sigor@sysoev.ru         }
1411240Sigor@sysoev.ru 
1412240Sigor@sysoev.ru         lang->module = NULL;
1413240Sigor@sysoev.ru 
1414240Sigor@sysoev.ru         ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map,
1415240Sigor@sysoev.ru                                   nxt_nitems(nxt_app_lang_module_map), lang);
1416240Sigor@sysoev.ru 
1417240Sigor@sysoev.ru         if (ret != NXT_OK) {
1418240Sigor@sysoev.ru             goto fail;
1419240Sigor@sysoev.ru         }
1420240Sigor@sysoev.ru 
1421356Svbart@nginx.com         nxt_debug(task, "lang %d %s \"%s\"",
1422356Svbart@nginx.com                   lang->type, lang->version, lang->file);
1423240Sigor@sysoev.ru     }
1424240Sigor@sysoev.ru 
1425240Sigor@sysoev.ru     qsort(rt->languages->elts, rt->languages->nelts,
1426240Sigor@sysoev.ru           sizeof(nxt_app_lang_module_t), nxt_app_lang_compare);
1427240Sigor@sysoev.ru 
1428240Sigor@sysoev.ru fail:
1429240Sigor@sysoev.ru 
1430240Sigor@sysoev.ru     nxt_mp_destroy(mp);
1431240Sigor@sysoev.ru 
1432240Sigor@sysoev.ru     ret = nxt_main_start_controller_process(task, rt);
1433240Sigor@sysoev.ru 
1434240Sigor@sysoev.ru     if (ret == NXT_OK) {
1435240Sigor@sysoev.ru         (void) nxt_main_start_router_process(task, rt);
1436240Sigor@sysoev.ru     }
1437240Sigor@sysoev.ru }
1438240Sigor@sysoev.ru 
1439240Sigor@sysoev.ru 
1440240Sigor@sysoev.ru static int nxt_cdecl
1441240Sigor@sysoev.ru nxt_app_lang_compare(const void *v1, const void *v2)
1442240Sigor@sysoev.ru {
1443240Sigor@sysoev.ru     int                          n;
1444240Sigor@sysoev.ru     const nxt_app_lang_module_t  *lang1, *lang2;
1445240Sigor@sysoev.ru 
1446240Sigor@sysoev.ru     lang1 = v1;
1447240Sigor@sysoev.ru     lang2 = v2;
1448240Sigor@sysoev.ru 
1449356Svbart@nginx.com     n = lang1->type - lang2->type;
1450258Sigor@sysoev.ru 
1451258Sigor@sysoev.ru     if (n != 0) {
1452258Sigor@sysoev.ru         return n;
1453258Sigor@sysoev.ru     }
1454258Sigor@sysoev.ru 
1455354Svbart@nginx.com     n = nxt_strverscmp(lang1->version, lang2->version);
1456240Sigor@sysoev.ru 
1457240Sigor@sysoev.ru     /* Negate result to move higher versions to the beginning. */
1458240Sigor@sysoev.ru 
1459240Sigor@sysoev.ru     return -n;
1460240Sigor@sysoev.ru }
1461314Svbart@nginx.com 
1462314Svbart@nginx.com 
1463314Svbart@nginx.com static void
1464314Svbart@nginx.com nxt_main_port_conf_store_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1465314Svbart@nginx.com {
1466352Smax.romanov@nginx.com     ssize_t        n, size, offset;
1467314Svbart@nginx.com     nxt_buf_t      *b;
1468314Svbart@nginx.com     nxt_int_t      ret;
1469314Svbart@nginx.com     nxt_file_t     file;
1470314Svbart@nginx.com     nxt_runtime_t  *rt;
1471314Svbart@nginx.com 
1472314Svbart@nginx.com     nxt_memzero(&file, sizeof(nxt_file_t));
1473314Svbart@nginx.com 
1474314Svbart@nginx.com     rt = task->thread->runtime;
1475314Svbart@nginx.com 
1476314Svbart@nginx.com     file.name = (nxt_file_name_t *) rt->conf_tmp;
1477314Svbart@nginx.com 
1478314Svbart@nginx.com     if (nxt_slow_path(nxt_file_open(task, &file, NXT_FILE_WRONLY,
1479314Svbart@nginx.com                                     NXT_FILE_TRUNCATE, NXT_FILE_OWNER_ACCESS)
1480314Svbart@nginx.com                       != NXT_OK))
1481314Svbart@nginx.com     {
1482314Svbart@nginx.com         goto error;
1483314Svbart@nginx.com     }
1484314Svbart@nginx.com 
1485352Smax.romanov@nginx.com     offset = 0;
1486352Smax.romanov@nginx.com 
1487314Svbart@nginx.com     for (b = msg->buf; b != NULL; b = b->next) {
1488314Svbart@nginx.com         size = nxt_buf_mem_used_size(&b->mem);
1489314Svbart@nginx.com 
1490352Smax.romanov@nginx.com         n = nxt_file_write(&file, b->mem.pos, size, offset);
1491314Svbart@nginx.com 
1492314Svbart@nginx.com         if (nxt_slow_path(n != size)) {
1493314Svbart@nginx.com             nxt_file_close(task, &file);
1494314Svbart@nginx.com             (void) nxt_file_delete(file.name);
1495314Svbart@nginx.com             goto error;
1496314Svbart@nginx.com         }
1497352Smax.romanov@nginx.com 
1498352Smax.romanov@nginx.com         offset += n;
1499314Svbart@nginx.com     }
1500314Svbart@nginx.com 
1501314Svbart@nginx.com     nxt_file_close(task, &file);
1502314Svbart@nginx.com 
1503314Svbart@nginx.com     ret = nxt_file_rename(file.name, (nxt_file_name_t *) rt->conf);
1504314Svbart@nginx.com 
1505314Svbart@nginx.com     if (nxt_fast_path(ret == NXT_OK)) {
1506314Svbart@nginx.com         return;
1507314Svbart@nginx.com     }
1508314Svbart@nginx.com 
1509314Svbart@nginx.com error:
1510314Svbart@nginx.com 
1511564Svbart@nginx.com     nxt_alert(task, "failed to store current configuration");
1512314Svbart@nginx.com }
1513630Svbart@nginx.com 
1514630Svbart@nginx.com 
1515630Svbart@nginx.com static void
1516630Svbart@nginx.com nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1517630Svbart@nginx.com {
1518630Svbart@nginx.com     u_char               *path;
1519630Svbart@nginx.com     nxt_int_t            ret;
1520630Svbart@nginx.com     nxt_file_t           file;
1521630Svbart@nginx.com     nxt_port_t           *port;
1522630Svbart@nginx.com     nxt_port_msg_type_t  type;
1523630Svbart@nginx.com 
1524630Svbart@nginx.com     nxt_debug(task, "opening access log file");
1525630Svbart@nginx.com 
1526630Svbart@nginx.com     path = msg->buf->mem.pos;
1527630Svbart@nginx.com 
1528630Svbart@nginx.com     nxt_memzero(&file, sizeof(nxt_file_t));
1529630Svbart@nginx.com 
1530630Svbart@nginx.com     file.name = (nxt_file_name_t *) path;
1531630Svbart@nginx.com     file.log_level = NXT_LOG_ERR;
1532630Svbart@nginx.com 
1533630Svbart@nginx.com     ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT,
1534630Svbart@nginx.com                         NXT_FILE_OWNER_ACCESS);
1535630Svbart@nginx.com 
1536630Svbart@nginx.com     type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD
1537630Svbart@nginx.com                            : NXT_PORT_MSG_RPC_ERROR;
1538630Svbart@nginx.com 
1539630Svbart@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1540630Svbart@nginx.com                                  msg->port_msg.reply_port);
1541630Svbart@nginx.com 
1542630Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
1543630Svbart@nginx.com         (void) nxt_port_socket_write(task, port, type, file.fd,
1544630Svbart@nginx.com                                      msg->port_msg.stream, 0, NULL);
1545630Svbart@nginx.com     }
1546630Svbart@nginx.com }
15471182St.nateldemoura@f5.com 
15481182St.nateldemoura@f5.com 
15491182St.nateldemoura@f5.com static nxt_int_t
15501306St.nateldemoura@f5.com nxt_init_isolation(nxt_task_t *task, nxt_conf_value_t *isolation,
15511306St.nateldemoura@f5.com     nxt_process_init_t *init)
15521306St.nateldemoura@f5.com {
15531306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE)
15541306St.nateldemoura@f5.com     nxt_int_t         ret;
15551306St.nateldemoura@f5.com     nxt_conf_value_t  *obj;
15561306St.nateldemoura@f5.com 
15571306St.nateldemoura@f5.com     static nxt_str_t  nsname = nxt_string("namespaces");
15581306St.nateldemoura@f5.com 
15591306St.nateldemoura@f5.com     obj = nxt_conf_get_object_member(isolation, &nsname, NULL);
15601306St.nateldemoura@f5.com     if (obj != NULL) {
15611306St.nateldemoura@f5.com         ret = nxt_init_clone_flags(task, obj, init);
15621306St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
15631306St.nateldemoura@f5.com             return NXT_ERROR;
15641306St.nateldemoura@f5.com         }
15651306St.nateldemoura@f5.com     }
15661306St.nateldemoura@f5.com #endif
15671306St.nateldemoura@f5.com 
15681306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER)
15691306St.nateldemoura@f5.com     ret = nxt_init_isolation_creds(task, isolation, init);
15701306St.nateldemoura@f5.com     if (nxt_slow_path(ret != NXT_OK)) {
15711306St.nateldemoura@f5.com         return NXT_ERROR;
15721306St.nateldemoura@f5.com     }
15731306St.nateldemoura@f5.com #endif
15741306St.nateldemoura@f5.com 
15751306St.nateldemoura@f5.com     return NXT_OK;
15761306St.nateldemoura@f5.com }
15771306St.nateldemoura@f5.com 
15781306St.nateldemoura@f5.com 
15791306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER)
15801306St.nateldemoura@f5.com 
15811306St.nateldemoura@f5.com static nxt_int_t
15821306St.nateldemoura@f5.com nxt_init_isolation_creds(nxt_task_t *task, nxt_conf_value_t *isolation,
15831306St.nateldemoura@f5.com     nxt_process_init_t *init)
15841182St.nateldemoura@f5.com {
15851182St.nateldemoura@f5.com     nxt_int_t         ret;
15861306St.nateldemoura@f5.com     nxt_clone_t       *clone;
15871306St.nateldemoura@f5.com     nxt_conf_value_t  *array;
15881182St.nateldemoura@f5.com 
15891182St.nateldemoura@f5.com     static nxt_str_t uidname = nxt_string("uidmap");
15901182St.nateldemoura@f5.com     static nxt_str_t gidname = nxt_string("gidmap");
15911182St.nateldemoura@f5.com 
15921306St.nateldemoura@f5.com     clone = &init->isolation.clone;
15931182St.nateldemoura@f5.com 
15941306St.nateldemoura@f5.com     array = nxt_conf_get_object_member(isolation, &uidname, NULL);
15951306St.nateldemoura@f5.com     if (array != NULL) {
15961306St.nateldemoura@f5.com         ret = nxt_init_isolation_credential_map(task, init->mem_pool, array,
15971306St.nateldemoura@f5.com                                                 &clone->uidmap);
15981306St.nateldemoura@f5.com 
15991306St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
16001306St.nateldemoura@f5.com             return NXT_ERROR;
16011182St.nateldemoura@f5.com         }
16021182St.nateldemoura@f5.com     }
16031182St.nateldemoura@f5.com 
16041306St.nateldemoura@f5.com     array = nxt_conf_get_object_member(isolation, &gidname, NULL);
16051306St.nateldemoura@f5.com     if (array != NULL) {
16061306St.nateldemoura@f5.com         ret = nxt_init_isolation_credential_map(task, init->mem_pool, array,
16071306St.nateldemoura@f5.com                                                 &clone->gidmap);
16081182St.nateldemoura@f5.com 
16091306St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
16101306St.nateldemoura@f5.com             return NXT_ERROR;
16111306St.nateldemoura@f5.com         }
16121182St.nateldemoura@f5.com     }
16131182St.nateldemoura@f5.com 
16141182St.nateldemoura@f5.com     return NXT_OK;
16151182St.nateldemoura@f5.com }
16161182St.nateldemoura@f5.com 
16171182St.nateldemoura@f5.com 
16181182St.nateldemoura@f5.com static nxt_int_t
16191306St.nateldemoura@f5.com nxt_init_vldt_isolation_creds(nxt_task_t *task, nxt_process_init_t *init)
16201306St.nateldemoura@f5.com {
16211306St.nateldemoura@f5.com     nxt_int_t    ret;
16221306St.nateldemoura@f5.com     nxt_clone_t  *clone;
16231306St.nateldemoura@f5.com 
16241306St.nateldemoura@f5.com     clone = &init->isolation.clone;
16251306St.nateldemoura@f5.com 
16261306St.nateldemoura@f5.com     if (clone->uidmap.size == 0 && clone->gidmap.size == 0) {
16271306St.nateldemoura@f5.com         return NXT_OK;
16281306St.nateldemoura@f5.com     }
16291306St.nateldemoura@f5.com 
16301306St.nateldemoura@f5.com     if (!NXT_CLONE_USER(clone->flags)) {
16311306St.nateldemoura@f5.com         if (nxt_slow_path(clone->uidmap.size > 0)) {
16321306St.nateldemoura@f5.com             nxt_log(task, NXT_LOG_ERR, "\"uidmap\" is set but "
16331306St.nateldemoura@f5.com                     "\"isolation.namespaces.credential\" is false or unset");
16341306St.nateldemoura@f5.com 
16351306St.nateldemoura@f5.com             return NXT_ERROR;
16361306St.nateldemoura@f5.com         }
16371306St.nateldemoura@f5.com 
16381306St.nateldemoura@f5.com         if (nxt_slow_path(clone->gidmap.size > 0)) {
16391306St.nateldemoura@f5.com             nxt_log(task, NXT_LOG_ERR, "\"gidmap\" is set but "
16401306St.nateldemoura@f5.com                     "\"isolation.namespaces.credential\" is false or unset");
16411306St.nateldemoura@f5.com 
16421306St.nateldemoura@f5.com             return NXT_ERROR;
16431306St.nateldemoura@f5.com         }
16441306St.nateldemoura@f5.com 
16451306St.nateldemoura@f5.com         return NXT_OK;
16461306St.nateldemoura@f5.com     }
16471306St.nateldemoura@f5.com 
16481306St.nateldemoura@f5.com     ret = nxt_clone_vldt_credential_uidmap(task, &clone->uidmap,
16491306St.nateldemoura@f5.com                                            init->user_cred);
16501306St.nateldemoura@f5.com 
16511306St.nateldemoura@f5.com     if (nxt_slow_path(ret != NXT_OK)) {
16521306St.nateldemoura@f5.com         return NXT_ERROR;
16531306St.nateldemoura@f5.com     }
16541306St.nateldemoura@f5.com 
16551306St.nateldemoura@f5.com     return nxt_clone_vldt_credential_gidmap(task, &clone->gidmap,
16561306St.nateldemoura@f5.com                                             init->user_cred);
16571306St.nateldemoura@f5.com }
16581306St.nateldemoura@f5.com 
16591306St.nateldemoura@f5.com 
16601306St.nateldemoura@f5.com static nxt_int_t
16611306St.nateldemoura@f5.com nxt_init_isolation_credential_map(nxt_task_t *task, nxt_mp_t *mem_pool,
16621306St.nateldemoura@f5.com     nxt_conf_value_t *map_array, nxt_clone_credential_map_t *map)
16631306St.nateldemoura@f5.com {
16641306St.nateldemoura@f5.com     nxt_int_t         ret;
16651306St.nateldemoura@f5.com     nxt_uint_t        i;
16661306St.nateldemoura@f5.com     nxt_conf_value_t  *obj;
16671306St.nateldemoura@f5.com 
16681306St.nateldemoura@f5.com     static nxt_conf_map_t  nxt_clone_map_entry_conf[] = {
16691306St.nateldemoura@f5.com         {
16701306St.nateldemoura@f5.com             nxt_string("container"),
16711306St.nateldemoura@f5.com             NXT_CONF_MAP_INT,
16721306St.nateldemoura@f5.com             offsetof(nxt_clone_map_entry_t, container),
16731306St.nateldemoura@f5.com         },
16741306St.nateldemoura@f5.com 
16751306St.nateldemoura@f5.com         {
16761306St.nateldemoura@f5.com             nxt_string("host"),
16771306St.nateldemoura@f5.com             NXT_CONF_MAP_INT,
16781306St.nateldemoura@f5.com             offsetof(nxt_clone_map_entry_t, host),
16791306St.nateldemoura@f5.com         },
16801306St.nateldemoura@f5.com 
16811306St.nateldemoura@f5.com         {
16821306St.nateldemoura@f5.com             nxt_string("size"),
16831306St.nateldemoura@f5.com             NXT_CONF_MAP_INT,
16841306St.nateldemoura@f5.com             offsetof(nxt_clone_map_entry_t, size),
16851306St.nateldemoura@f5.com         },
16861306St.nateldemoura@f5.com     };
16871306St.nateldemoura@f5.com 
16881306St.nateldemoura@f5.com     map->size = nxt_conf_array_elements_count(map_array);
16891306St.nateldemoura@f5.com 
16901306St.nateldemoura@f5.com     if (map->size == 0) {
16911306St.nateldemoura@f5.com         return NXT_OK;
16921306St.nateldemoura@f5.com     }
16931306St.nateldemoura@f5.com 
16941306St.nateldemoura@f5.com     map->map = nxt_mp_alloc(mem_pool,
16951306St.nateldemoura@f5.com                             map->size * sizeof(nxt_clone_map_entry_t));
16961306St.nateldemoura@f5.com     if (nxt_slow_path(map->map == NULL)) {
16971306St.nateldemoura@f5.com         return NXT_ERROR;
16981306St.nateldemoura@f5.com     }
16991306St.nateldemoura@f5.com 
17001306St.nateldemoura@f5.com     for (i = 0; i < map->size; i++) {
17011306St.nateldemoura@f5.com         obj = nxt_conf_get_array_element(map_array, i);
17021306St.nateldemoura@f5.com 
17031306St.nateldemoura@f5.com         ret = nxt_conf_map_object(mem_pool, obj, nxt_clone_map_entry_conf,
17041306St.nateldemoura@f5.com                                   nxt_nitems(nxt_clone_map_entry_conf),
17051306St.nateldemoura@f5.com                                   map->map + i);
17061306St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
17071306St.nateldemoura@f5.com             nxt_alert(task, "clone map entry map error");
17081306St.nateldemoura@f5.com             return NXT_ERROR;
17091306St.nateldemoura@f5.com         }
17101306St.nateldemoura@f5.com     }
17111306St.nateldemoura@f5.com 
17121306St.nateldemoura@f5.com     return NXT_OK;
17131306St.nateldemoura@f5.com }
17141306St.nateldemoura@f5.com 
17151306St.nateldemoura@f5.com #endif
17161306St.nateldemoura@f5.com 
17171306St.nateldemoura@f5.com #if (NXT_HAVE_CLONE)
17181306St.nateldemoura@f5.com 
17191306St.nateldemoura@f5.com static nxt_int_t
17201306St.nateldemoura@f5.com nxt_init_clone_flags(nxt_task_t *task, nxt_conf_value_t *namespaces,
17211306St.nateldemoura@f5.com     nxt_process_init_t *init)
17221182St.nateldemoura@f5.com {
17231182St.nateldemoura@f5.com     uint32_t          index;
17241182St.nateldemoura@f5.com     nxt_str_t         name;
17251182St.nateldemoura@f5.com     nxt_int_t         flag;
17261182St.nateldemoura@f5.com     nxt_conf_value_t  *value;
17271182St.nateldemoura@f5.com 
17281182St.nateldemoura@f5.com     index = 0;
17291182St.nateldemoura@f5.com 
17301235Sigor@sysoev.ru     for ( ;; ) {
17311235Sigor@sysoev.ru         value = nxt_conf_next_object_member(namespaces, &name, &index);
17321235Sigor@sysoev.ru 
17331235Sigor@sysoev.ru         if (value == NULL) {
17341235Sigor@sysoev.ru             break;
17351235Sigor@sysoev.ru         }
17361235Sigor@sysoev.ru 
17371182St.nateldemoura@f5.com         flag = 0;
17381182St.nateldemoura@f5.com 
17391182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUSER)
17401182St.nateldemoura@f5.com         if (nxt_str_eq(&name, "credential", 10)) {
17411182St.nateldemoura@f5.com             flag = CLONE_NEWUSER;
17421182St.nateldemoura@f5.com         }
17431182St.nateldemoura@f5.com #endif
17441182St.nateldemoura@f5.com 
17451182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWPID)
17461182St.nateldemoura@f5.com         if (nxt_str_eq(&name, "pid", 3)) {
17471182St.nateldemoura@f5.com             flag = CLONE_NEWPID;
17481182St.nateldemoura@f5.com         }
17491182St.nateldemoura@f5.com #endif
17501182St.nateldemoura@f5.com 
17511182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNET)
17521182St.nateldemoura@f5.com         if (nxt_str_eq(&name, "network", 7)) {
17531182St.nateldemoura@f5.com             flag = CLONE_NEWNET;
17541182St.nateldemoura@f5.com         }
17551182St.nateldemoura@f5.com #endif
17561182St.nateldemoura@f5.com 
17571182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWUTS)
17581182St.nateldemoura@f5.com         if (nxt_str_eq(&name, "uname", 5)) {
17591182St.nateldemoura@f5.com             flag = CLONE_NEWUTS;
17601182St.nateldemoura@f5.com         }
17611182St.nateldemoura@f5.com #endif
17621182St.nateldemoura@f5.com 
17631182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWNS)
17641182St.nateldemoura@f5.com         if (nxt_str_eq(&name, "mount", 5)) {
17651182St.nateldemoura@f5.com             flag = CLONE_NEWNS;
17661182St.nateldemoura@f5.com         }
17671182St.nateldemoura@f5.com #endif
17681182St.nateldemoura@f5.com 
17691182St.nateldemoura@f5.com #if (NXT_HAVE_CLONE_NEWCGROUP)
17701182St.nateldemoura@f5.com         if (nxt_str_eq(&name, "cgroup", 6)) {
17711182St.nateldemoura@f5.com             flag = CLONE_NEWCGROUP;
17721182St.nateldemoura@f5.com         }
17731182St.nateldemoura@f5.com #endif
17741182St.nateldemoura@f5.com 
17751182St.nateldemoura@f5.com         if (!flag) {
17761182St.nateldemoura@f5.com             nxt_alert(task, "unknown namespace flag: \"%V\"", &name);
17771182St.nateldemoura@f5.com             return NXT_ERROR;
17781182St.nateldemoura@f5.com         }
17791182St.nateldemoura@f5.com 
17801236St.nateldemoura@f5.com         if (nxt_conf_get_boolean(value)) {
17811236St.nateldemoura@f5.com             init->isolation.clone.flags |= flag;
17821182St.nateldemoura@f5.com         }
17831182St.nateldemoura@f5.com     }
17841182St.nateldemoura@f5.com 
17851182St.nateldemoura@f5.com     return NXT_OK;
17861182St.nateldemoura@f5.com }
17871302St.nateldemoura@f5.com 
17881306St.nateldemoura@f5.com #endif
17891306St.nateldemoura@f5.com 
17901302St.nateldemoura@f5.com 
17911302St.nateldemoura@f5.com static nxt_process_init_t *
17921302St.nateldemoura@f5.com nxt_process_init_create(nxt_task_t *task, nxt_process_type_t type,
17931302St.nateldemoura@f5.com     const nxt_str_t *name)
17941302St.nateldemoura@f5.com {
17951302St.nateldemoura@f5.com     nxt_mp_t            *mp;
17961302St.nateldemoura@f5.com     nxt_int_t           ret;
17971302St.nateldemoura@f5.com     nxt_runtime_t       *rt;
17981302St.nateldemoura@f5.com     nxt_process_init_t  *init;
17991302St.nateldemoura@f5.com 
18001302St.nateldemoura@f5.com     mp = nxt_mp_create(1024, 128, 256, 32);
18011302St.nateldemoura@f5.com     if (nxt_slow_path(mp == NULL)) {
18021302St.nateldemoura@f5.com         return NULL;
18031302St.nateldemoura@f5.com     }
18041302St.nateldemoura@f5.com 
18051302St.nateldemoura@f5.com     init = nxt_mp_zalloc(mp, sizeof(nxt_process_init_t));
18061302St.nateldemoura@f5.com     if (nxt_slow_path(init == NULL)) {
18071302St.nateldemoura@f5.com         goto fail;
18081302St.nateldemoura@f5.com     }
18091302St.nateldemoura@f5.com 
18101302St.nateldemoura@f5.com     init->mem_pool = mp;
18111302St.nateldemoura@f5.com 
18121302St.nateldemoura@f5.com     ret = nxt_process_init_name_set(init, type, name);
18131302St.nateldemoura@f5.com     if (nxt_slow_path(ret != NXT_OK)) {
18141302St.nateldemoura@f5.com         goto fail;
18151302St.nateldemoura@f5.com     }
18161302St.nateldemoura@f5.com 
18171302St.nateldemoura@f5.com     rt = task->thread->runtime;
18181302St.nateldemoura@f5.com 
18191302St.nateldemoura@f5.com     init->type = type;
18201302St.nateldemoura@f5.com     init->start = nxt_process_starts[type];
18211302St.nateldemoura@f5.com     init->port_handlers = nxt_process_port_handlers[type];
18221302St.nateldemoura@f5.com     init->signals = nxt_worker_process_signals;
18231302St.nateldemoura@f5.com     init->user_cred = &rt->user_cred;
18241302St.nateldemoura@f5.com     init->data = &rt;
18251302St.nateldemoura@f5.com 
18261302St.nateldemoura@f5.com     return init;
18271302St.nateldemoura@f5.com 
18281302St.nateldemoura@f5.com fail:
18291302St.nateldemoura@f5.com 
18301302St.nateldemoura@f5.com     nxt_mp_destroy(mp);
18311302St.nateldemoura@f5.com 
18321302St.nateldemoura@f5.com     return NULL;
18331302St.nateldemoura@f5.com }
18341302St.nateldemoura@f5.com 
18351302St.nateldemoura@f5.com 
18361302St.nateldemoura@f5.com static nxt_int_t
18371302St.nateldemoura@f5.com nxt_process_init_name_set(nxt_process_init_t *init, nxt_process_type_t type,
18381302St.nateldemoura@f5.com     const nxt_str_t *name)
18391302St.nateldemoura@f5.com {
18401302St.nateldemoura@f5.com     u_char      *str, *end;
18411302St.nateldemoura@f5.com     size_t      size;
18421302St.nateldemoura@f5.com     const char  *fmt;
18431302St.nateldemoura@f5.com 
18441302St.nateldemoura@f5.com     size = name->length + 1;
18451302St.nateldemoura@f5.com 
18461302St.nateldemoura@f5.com     if (type == NXT_PROCESS_WORKER) {
18471302St.nateldemoura@f5.com         size += nxt_length("\"\" application");
18481302St.nateldemoura@f5.com         fmt = "\"%V\" application%Z";
18491302St.nateldemoura@f5.com 
18501302St.nateldemoura@f5.com     } else {
18511302St.nateldemoura@f5.com         fmt = "%V%Z";
18521302St.nateldemoura@f5.com     }
18531302St.nateldemoura@f5.com 
18541302St.nateldemoura@f5.com     str = nxt_mp_alloc(init->mem_pool, size);
18551302St.nateldemoura@f5.com     if (nxt_slow_path(str == NULL)) {
18561302St.nateldemoura@f5.com         return NXT_ERROR;
18571302St.nateldemoura@f5.com     }
18581302St.nateldemoura@f5.com 
18591302St.nateldemoura@f5.com     end = str + size;
18601302St.nateldemoura@f5.com 
18611302St.nateldemoura@f5.com     nxt_sprintf(str, end, fmt, name);
18621302St.nateldemoura@f5.com 
18631302St.nateldemoura@f5.com     init->name = (char *) str;
18641302St.nateldemoura@f5.com 
18651302St.nateldemoura@f5.com     return NXT_OK;
18661302St.nateldemoura@f5.com }
18671302St.nateldemoura@f5.com 
18681302St.nateldemoura@f5.com 
18691302St.nateldemoura@f5.com static nxt_int_t
18701302St.nateldemoura@f5.com nxt_process_init_creds_set(nxt_task_t *task, nxt_process_init_t *init,
18711302St.nateldemoura@f5.com     nxt_str_t *user, nxt_str_t *group)
18721302St.nateldemoura@f5.com {
18731302St.nateldemoura@f5.com     char  *str;
18741302St.nateldemoura@f5.com 
18751305St.nateldemoura@f5.com     init->user_cred = nxt_mp_zalloc(init->mem_pool, sizeof(nxt_credential_t));
18761302St.nateldemoura@f5.com 
18771302St.nateldemoura@f5.com     if (nxt_slow_path(init->user_cred == NULL)) {
18781302St.nateldemoura@f5.com         return NXT_ERROR;
18791302St.nateldemoura@f5.com     }
18801302St.nateldemoura@f5.com 
18811302St.nateldemoura@f5.com     str = nxt_mp_zalloc(init->mem_pool, user->length + 1);
18821302St.nateldemoura@f5.com     if (nxt_slow_path(str == NULL)) {
18831302St.nateldemoura@f5.com         return NXT_ERROR;
18841302St.nateldemoura@f5.com     }
18851302St.nateldemoura@f5.com 
18861302St.nateldemoura@f5.com     nxt_memcpy(str, user->start, user->length);
18871302St.nateldemoura@f5.com     str[user->length] = '\0';
18881302St.nateldemoura@f5.com 
18891302St.nateldemoura@f5.com     init->user_cred->user = str;
18901302St.nateldemoura@f5.com 
18911302St.nateldemoura@f5.com     if (group->start != NULL) {
18921302St.nateldemoura@f5.com         str = nxt_mp_zalloc(init->mem_pool, group->length + 1);
18931302St.nateldemoura@f5.com         if (nxt_slow_path(str == NULL)) {
18941302St.nateldemoura@f5.com             return NXT_ERROR;
18951302St.nateldemoura@f5.com         }
18961302St.nateldemoura@f5.com 
18971302St.nateldemoura@f5.com         nxt_memcpy(str, group->start, group->length);
18981302St.nateldemoura@f5.com         str[group->length] = '\0';
18991302St.nateldemoura@f5.com 
19001302St.nateldemoura@f5.com     } else {
19011302St.nateldemoura@f5.com         str = NULL;
19021302St.nateldemoura@f5.com     }
19031302St.nateldemoura@f5.com 
19041305St.nateldemoura@f5.com     return nxt_credential_get(task, init->mem_pool, init->user_cred, str);
19051302St.nateldemoura@f5.com }
1906