xref: /unit/src/nxt_main_process.c (revision 1681)
1240Sigor@sysoev.ru 
2240Sigor@sysoev.ru /*
3240Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
4240Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
5240Sigor@sysoev.ru  */
6240Sigor@sysoev.ru 
7240Sigor@sysoev.ru #include <nxt_main.h>
8240Sigor@sysoev.ru #include <nxt_runtime.h>
9240Sigor@sysoev.ru #include <nxt_port.h>
10240Sigor@sysoev.ru #include <nxt_main_process.h>
11240Sigor@sysoev.ru #include <nxt_conf.h>
12444Sigor@sysoev.ru #include <nxt_router.h>
13774Svbart@nginx.com #if (NXT_TLS)
14774Svbart@nginx.com #include <nxt_cert.h>
15774Svbart@nginx.com #endif
16240Sigor@sysoev.ru 
171489St.nateldemoura@f5.com #include <sys/mount.h>
181489St.nateldemoura@f5.com 
19240Sigor@sysoev.ru 
20240Sigor@sysoev.ru typedef struct {
21240Sigor@sysoev.ru     nxt_socket_t        socket;
22240Sigor@sysoev.ru     nxt_socket_error_t  error;
23240Sigor@sysoev.ru     u_char              *start;
24240Sigor@sysoev.ru     u_char              *end;
25240Sigor@sysoev.ru } nxt_listening_socket_t;
26240Sigor@sysoev.ru 
27240Sigor@sysoev.ru 
28510Salexander.borisov@nginx.com typedef struct {
29536Svbart@nginx.com     nxt_uint_t          size;
30536Svbart@nginx.com     nxt_conf_map_t      *map;
31546Smax.romanov@nginx.com } nxt_conf_app_map_t;
32510Salexander.borisov@nginx.com 
33510Salexander.borisov@nginx.com 
341302St.nateldemoura@f5.com extern nxt_port_handlers_t  nxt_controller_process_port_handlers;
351302St.nateldemoura@f5.com extern nxt_port_handlers_t  nxt_router_process_port_handlers;
361302St.nateldemoura@f5.com 
371302St.nateldemoura@f5.com 
38240Sigor@sysoev.ru static nxt_int_t nxt_main_process_port_create(nxt_task_t *task,
39240Sigor@sysoev.ru     nxt_runtime_t *rt);
40240Sigor@sysoev.ru static void nxt_main_process_title(nxt_task_t *task);
411488St.nateldemoura@f5.com static nxt_int_t nxt_main_process_create(nxt_task_t *task,
421488St.nateldemoura@f5.com     const nxt_process_init_t init);
431488St.nateldemoura@f5.com static nxt_int_t nxt_main_start_process(nxt_task_t *task,
441488St.nateldemoura@f5.com     nxt_process_t *process);
451488St.nateldemoura@f5.com static nxt_process_t *nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt);
46240Sigor@sysoev.ru static void nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj,
47240Sigor@sysoev.ru     void *data);
48240Sigor@sysoev.ru static void nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj,
49240Sigor@sysoev.ru     void *data);
50240Sigor@sysoev.ru static void nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj,
51240Sigor@sysoev.ru     void *data);
52240Sigor@sysoev.ru static void nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj,
53240Sigor@sysoev.ru     void *data);
54944Sigor@sysoev.ru static void nxt_main_process_signal_handler(nxt_task_t *task, void *obj,
55944Sigor@sysoev.ru     void *data);
561488St.nateldemoura@f5.com static void nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid);
57240Sigor@sysoev.ru static void nxt_main_port_socket_handler(nxt_task_t *task,
58240Sigor@sysoev.ru     nxt_port_recv_msg_t *msg);
59240Sigor@sysoev.ru static nxt_int_t nxt_main_listening_socket(nxt_sockaddr_t *sa,
60240Sigor@sysoev.ru     nxt_listening_socket_t *ls);
61240Sigor@sysoev.ru static void nxt_main_port_modules_handler(nxt_task_t *task,
62240Sigor@sysoev.ru     nxt_port_recv_msg_t *msg);
63240Sigor@sysoev.ru static int nxt_cdecl nxt_app_lang_compare(const void *v1, const void *v2);
64314Svbart@nginx.com static void nxt_main_port_conf_store_handler(nxt_task_t *task,
65314Svbart@nginx.com     nxt_port_recv_msg_t *msg);
66630Svbart@nginx.com static void nxt_main_port_access_log_handler(nxt_task_t *task,
67630Svbart@nginx.com     nxt_port_recv_msg_t *msg);
68240Sigor@sysoev.ru 
69240Sigor@sysoev.ru const nxt_sig_event_t  nxt_main_process_signals[] = {
70944Sigor@sysoev.ru     nxt_event_signal(SIGHUP,  nxt_main_process_signal_handler),
71240Sigor@sysoev.ru     nxt_event_signal(SIGINT,  nxt_main_process_sigterm_handler),
72240Sigor@sysoev.ru     nxt_event_signal(SIGQUIT, nxt_main_process_sigquit_handler),
73240Sigor@sysoev.ru     nxt_event_signal(SIGTERM, nxt_main_process_sigterm_handler),
74240Sigor@sysoev.ru     nxt_event_signal(SIGCHLD, nxt_main_process_sigchld_handler),
75240Sigor@sysoev.ru     nxt_event_signal(SIGUSR1, nxt_main_process_sigusr1_handler),
76240Sigor@sysoev.ru     nxt_event_signal_end,
77240Sigor@sysoev.ru };
78240Sigor@sysoev.ru 
79240Sigor@sysoev.ru 
80240Sigor@sysoev.ru static nxt_bool_t  nxt_exiting;
81240Sigor@sysoev.ru 
82240Sigor@sysoev.ru 
83240Sigor@sysoev.ru nxt_int_t
84240Sigor@sysoev.ru nxt_main_process_start(nxt_thread_t *thr, nxt_task_t *task,
85240Sigor@sysoev.ru     nxt_runtime_t *rt)
86240Sigor@sysoev.ru {
87696Sigor@sysoev.ru     rt->type = NXT_PROCESS_MAIN;
88240Sigor@sysoev.ru 
89240Sigor@sysoev.ru     if (nxt_main_process_port_create(task, rt) != NXT_OK) {
90240Sigor@sysoev.ru         return NXT_ERROR;
91240Sigor@sysoev.ru     }
92240Sigor@sysoev.ru 
93240Sigor@sysoev.ru     nxt_main_process_title(task);
94240Sigor@sysoev.ru 
95240Sigor@sysoev.ru     /*
961488St.nateldemoura@f5.com      * The discovery process will send a message processed by
97240Sigor@sysoev.ru      * nxt_main_port_modules_handler() which starts the controller
98240Sigor@sysoev.ru      * and router processes.
99240Sigor@sysoev.ru      */
1001488St.nateldemoura@f5.com     return nxt_main_process_create(task, nxt_discovery_process);
101240Sigor@sysoev.ru }
102240Sigor@sysoev.ru 
103240Sigor@sysoev.ru 
104240Sigor@sysoev.ru static nxt_conf_map_t  nxt_common_app_conf[] = {
105240Sigor@sysoev.ru     {
106240Sigor@sysoev.ru         nxt_string("type"),
107240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
108240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, type),
109240Sigor@sysoev.ru     },
110240Sigor@sysoev.ru 
111240Sigor@sysoev.ru     {
112240Sigor@sysoev.ru         nxt_string("user"),
113240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
114240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, user),
115240Sigor@sysoev.ru     },
116240Sigor@sysoev.ru 
117240Sigor@sysoev.ru     {
118240Sigor@sysoev.ru         nxt_string("group"),
119240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
120240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, group),
121240Sigor@sysoev.ru     },
122240Sigor@sysoev.ru 
123240Sigor@sysoev.ru     {
124271Smax.romanov@nginx.com         nxt_string("working_directory"),
125271Smax.romanov@nginx.com         NXT_CONF_MAP_CSTRZ,
126271Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, working_directory),
127271Smax.romanov@nginx.com     },
128678Svbart@nginx.com 
129678Svbart@nginx.com     {
130678Svbart@nginx.com         nxt_string("environment"),
131678Svbart@nginx.com         NXT_CONF_MAP_PTR,
132678Svbart@nginx.com         offsetof(nxt_common_app_conf_t, environment),
133678Svbart@nginx.com     },
1341182St.nateldemoura@f5.com 
1351182St.nateldemoura@f5.com     {
1361182St.nateldemoura@f5.com         nxt_string("isolation"),
1371182St.nateldemoura@f5.com         NXT_CONF_MAP_PTR,
1381182St.nateldemoura@f5.com         offsetof(nxt_common_app_conf_t, isolation),
1391320Smax.romanov@nginx.com     },
1401320Smax.romanov@nginx.com 
1411320Smax.romanov@nginx.com     {
1421320Smax.romanov@nginx.com         nxt_string("limits"),
1431320Smax.romanov@nginx.com         NXT_CONF_MAP_PTR,
1441320Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, limits),
1451320Smax.romanov@nginx.com     },
1461320Smax.romanov@nginx.com 
1471320Smax.romanov@nginx.com };
1481320Smax.romanov@nginx.com 
1491320Smax.romanov@nginx.com 
1501320Smax.romanov@nginx.com static nxt_conf_map_t  nxt_common_app_limits_conf[] = {
1511320Smax.romanov@nginx.com     {
1521320Smax.romanov@nginx.com         nxt_string("shm"),
1531320Smax.romanov@nginx.com         NXT_CONF_MAP_SIZE,
1541320Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, shm_limit),
1551320Smax.romanov@nginx.com     },
1561320Smax.romanov@nginx.com 
157510Salexander.borisov@nginx.com };
158271Smax.romanov@nginx.com 
159510Salexander.borisov@nginx.com 
160804Svbart@nginx.com static nxt_conf_map_t  nxt_external_app_conf[] = {
161804Svbart@nginx.com     {
162804Svbart@nginx.com         nxt_string("executable"),
163804Svbart@nginx.com         NXT_CONF_MAP_CSTRZ,
164804Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.external.executable),
165804Svbart@nginx.com     },
166804Svbart@nginx.com 
167804Svbart@nginx.com     {
168804Svbart@nginx.com         nxt_string("arguments"),
169804Svbart@nginx.com         NXT_CONF_MAP_PTR,
170804Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.external.arguments),
171804Svbart@nginx.com     },
172804Svbart@nginx.com 
173804Svbart@nginx.com };
174804Svbart@nginx.com 
175804Svbart@nginx.com 
176546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_python_app_conf[] = {
177271Smax.romanov@nginx.com     {
178394Smax.romanov@nginx.com         nxt_string("home"),
179394Smax.romanov@nginx.com         NXT_CONF_MAP_CSTRZ,
180394Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.home),
181394Smax.romanov@nginx.com     },
182394Smax.romanov@nginx.com 
183394Smax.romanov@nginx.com     {
184240Sigor@sysoev.ru         nxt_string("path"),
185240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
186240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, u.python.path),
187240Sigor@sysoev.ru     },
188240Sigor@sysoev.ru 
189240Sigor@sysoev.ru     {
190240Sigor@sysoev.ru         nxt_string("module"),
191240Sigor@sysoev.ru         NXT_CONF_MAP_STR,
192240Sigor@sysoev.ru         offsetof(nxt_common_app_conf_t, u.python.module),
193240Sigor@sysoev.ru     },
1941601Smax.romanov@nginx.com 
1951601Smax.romanov@nginx.com     {
1961601Smax.romanov@nginx.com         nxt_string("callable"),
1971601Smax.romanov@nginx.com         NXT_CONF_MAP_CSTRZ,
1981601Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.callable),
1991601Smax.romanov@nginx.com     },
200*1681Smax.romanov@nginx.com 
201*1681Smax.romanov@nginx.com     {
202*1681Smax.romanov@nginx.com         nxt_string("threads"),
203*1681Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
204*1681Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.threads),
205*1681Smax.romanov@nginx.com     },
206*1681Smax.romanov@nginx.com 
207*1681Smax.romanov@nginx.com     {
208*1681Smax.romanov@nginx.com         nxt_string("thread_stack_size"),
209*1681Smax.romanov@nginx.com         NXT_CONF_MAP_INT32,
210*1681Smax.romanov@nginx.com         offsetof(nxt_common_app_conf_t, u.python.thread_stack_size),
211*1681Smax.romanov@nginx.com     },
212510Salexander.borisov@nginx.com };
213240Sigor@sysoev.ru 
214510Salexander.borisov@nginx.com 
215546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_php_app_conf[] = {
216240Sigor@sysoev.ru     {
2171473Svbart@nginx.com         nxt_string("targets"),
2181473Svbart@nginx.com         NXT_CONF_MAP_PTR,
2191473Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.php.targets),
220240Sigor@sysoev.ru     },
221687Svbart@nginx.com 
222687Svbart@nginx.com     {
223687Svbart@nginx.com         nxt_string("options"),
224687Svbart@nginx.com         NXT_CONF_MAP_PTR,
225687Svbart@nginx.com         offsetof(nxt_common_app_conf_t, u.php.options),
226687Svbart@nginx.com     },
227510Salexander.borisov@nginx.com };
228240Sigor@sysoev.ru 
229510Salexander.borisov@nginx.com 
230546Smax.romanov@nginx.com static nxt_conf_map_t  nxt_perl_app_conf[] = {
231510Salexander.borisov@nginx.com     {
232510Salexander.borisov@nginx.com         nxt_string("script"),
233510Salexander.borisov@nginx.com         NXT_CONF_MAP_CSTRZ,
234510Salexander.borisov@nginx.com         offsetof(nxt_common_app_conf_t, u.perl.script),
235510Salexander.borisov@nginx.com     },
236510Salexander.borisov@nginx.com };
237510Salexander.borisov@nginx.com 
238510Salexander.borisov@nginx.com 
239584Salexander.borisov@nginx.com static nxt_conf_map_t  nxt_ruby_app_conf[] = {
240584Salexander.borisov@nginx.com     {
241584Salexander.borisov@nginx.com         nxt_string("script"),
242584Salexander.borisov@nginx.com         NXT_CONF_MAP_STR,
243584Salexander.borisov@nginx.com         offsetof(nxt_common_app_conf_t, u.ruby.script),
244584Salexander.borisov@nginx.com     },
245584Salexander.borisov@nginx.com };
246584Salexander.borisov@nginx.com 
247584Salexander.borisov@nginx.com 
248977Smax.romanov@gmail.com static nxt_conf_map_t  nxt_java_app_conf[] = {
249977Smax.romanov@gmail.com     {
250977Smax.romanov@gmail.com         nxt_string("classpath"),
251977Smax.romanov@gmail.com         NXT_CONF_MAP_PTR,
252977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.classpath),
253977Smax.romanov@gmail.com     },
254977Smax.romanov@gmail.com     {
255977Smax.romanov@gmail.com         nxt_string("webapp"),
256977Smax.romanov@gmail.com         NXT_CONF_MAP_CSTRZ,
257977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.webapp),
258977Smax.romanov@gmail.com     },
259977Smax.romanov@gmail.com     {
260977Smax.romanov@gmail.com         nxt_string("options"),
261977Smax.romanov@gmail.com         NXT_CONF_MAP_PTR,
262977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.options),
263977Smax.romanov@gmail.com     },
264977Smax.romanov@gmail.com     {
265977Smax.romanov@gmail.com         nxt_string("unit_jars"),
266977Smax.romanov@gmail.com         NXT_CONF_MAP_CSTRZ,
267977Smax.romanov@gmail.com         offsetof(nxt_common_app_conf_t, u.java.unit_jars),
268977Smax.romanov@gmail.com     },
269977Smax.romanov@gmail.com 
270977Smax.romanov@gmail.com };
271977Smax.romanov@gmail.com 
272977Smax.romanov@gmail.com 
273546Smax.romanov@nginx.com static nxt_conf_app_map_t  nxt_app_maps[] = {
274804Svbart@nginx.com     { nxt_nitems(nxt_external_app_conf),  nxt_external_app_conf },
275804Svbart@nginx.com     { nxt_nitems(nxt_python_app_conf),    nxt_python_app_conf },
276804Svbart@nginx.com     { nxt_nitems(nxt_php_app_conf),       nxt_php_app_conf },
277804Svbart@nginx.com     { nxt_nitems(nxt_perl_app_conf),      nxt_perl_app_conf },
278804Svbart@nginx.com     { nxt_nitems(nxt_ruby_app_conf),      nxt_ruby_app_conf },
279977Smax.romanov@gmail.com     { nxt_nitems(nxt_java_app_conf),      nxt_java_app_conf },
280510Salexander.borisov@nginx.com };
281510Salexander.borisov@nginx.com 
282510Salexander.borisov@nginx.com 
283240Sigor@sysoev.ru static void
284240Sigor@sysoev.ru nxt_port_main_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
285240Sigor@sysoev.ru {
286240Sigor@sysoev.ru     nxt_debug(task, "main data: %*s",
287240Sigor@sysoev.ru               nxt_buf_mem_used_size(&msg->buf->mem), msg->buf->mem.pos);
288240Sigor@sysoev.ru }
289240Sigor@sysoev.ru 
290240Sigor@sysoev.ru 
291240Sigor@sysoev.ru static void
2921488St.nateldemoura@f5.com nxt_port_main_start_process_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
293240Sigor@sysoev.ru {
2941488St.nateldemoura@f5.com     u_char                 *start, *p, ch;
295536Svbart@nginx.com     size_t                 type_len;
296536Svbart@nginx.com     nxt_int_t              ret;
297240Sigor@sysoev.ru     nxt_buf_t              *b;
298318Smax.romanov@nginx.com     nxt_port_t             *port;
2991182St.nateldemoura@f5.com     nxt_runtime_t          *rt;
3001488St.nateldemoura@f5.com     nxt_process_t          *process;
301536Svbart@nginx.com     nxt_app_type_t         idx;
302240Sigor@sysoev.ru     nxt_conf_value_t       *conf;
3031488St.nateldemoura@f5.com     nxt_process_init_t     *init;
3041488St.nateldemoura@f5.com     nxt_common_app_conf_t  *app_conf;
305240Sigor@sysoev.ru 
306318Smax.romanov@nginx.com     ret = NXT_ERROR;
307318Smax.romanov@nginx.com 
3081488St.nateldemoura@f5.com     rt = task->thread->runtime;
309352Smax.romanov@nginx.com 
3101488St.nateldemoura@f5.com     process = nxt_main_process_new(task, rt);
3111488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
312352Smax.romanov@nginx.com         return;
313352Smax.romanov@nginx.com     }
314352Smax.romanov@nginx.com 
3151488St.nateldemoura@f5.com     init = nxt_process_init(process);
3161488St.nateldemoura@f5.com 
3171488St.nateldemoura@f5.com     *init = nxt_app_process;
318352Smax.romanov@nginx.com 
3191488St.nateldemoura@f5.com     b = nxt_buf_chk_make_plain(process->mem_pool, msg->buf, msg->size);
320352Smax.romanov@nginx.com     if (b == NULL) {
3211488St.nateldemoura@f5.com         goto failed;
322352Smax.romanov@nginx.com     }
323240Sigor@sysoev.ru 
3241488St.nateldemoura@f5.com     nxt_debug(task, "main start process: %*s", b->mem.free - b->mem.pos,
325240Sigor@sysoev.ru               b->mem.pos);
326240Sigor@sysoev.ru 
3271488St.nateldemoura@f5.com     app_conf = nxt_mp_zalloc(process->mem_pool, sizeof(nxt_common_app_conf_t));
3281488St.nateldemoura@f5.com     if (nxt_slow_path(app_conf == NULL)) {
3291488St.nateldemoura@f5.com         goto failed;
3301488St.nateldemoura@f5.com     }
331240Sigor@sysoev.ru 
332240Sigor@sysoev.ru     start = b->mem.pos;
333240Sigor@sysoev.ru 
3341488St.nateldemoura@f5.com     app_conf->name.start = start;
3351488St.nateldemoura@f5.com     app_conf->name.length = nxt_strlen(start);
3361488St.nateldemoura@f5.com 
3371488St.nateldemoura@f5.com     init->name = (const char *) start;
3381488St.nateldemoura@f5.com 
3391488St.nateldemoura@f5.com     process->name = nxt_mp_alloc(process->mem_pool, app_conf->name.length
3401488St.nateldemoura@f5.com                                  + sizeof("\"\" application") + 1);
3411488St.nateldemoura@f5.com 
3421488St.nateldemoura@f5.com     if (nxt_slow_path(process->name == NULL)) {
3431488St.nateldemoura@f5.com         goto failed;
3441488St.nateldemoura@f5.com     }
345240Sigor@sysoev.ru 
3461488St.nateldemoura@f5.com     p = (u_char *) process->name;
3471488St.nateldemoura@f5.com     *p++ = '"';
3481488St.nateldemoura@f5.com     p = nxt_cpymem(p, init->name, app_conf->name.length);
3491488St.nateldemoura@f5.com     p = nxt_cpymem(p, "\" application", 13);
3501488St.nateldemoura@f5.com     *p = '\0';
351240Sigor@sysoev.ru 
3521488St.nateldemoura@f5.com     app_conf->shm_limit = 100 * 1024 * 1024;
353240Sigor@sysoev.ru 
3541488St.nateldemoura@f5.com     start += app_conf->name.length + 1;
3551488St.nateldemoura@f5.com 
3561488St.nateldemoura@f5.com     conf = nxt_conf_json_parse(process->mem_pool, start, b->mem.free, NULL);
357240Sigor@sysoev.ru     if (conf == NULL) {
358564Svbart@nginx.com         nxt_alert(task, "router app configuration parsing error");
359318Smax.romanov@nginx.com 
360318Smax.romanov@nginx.com         goto failed;
361240Sigor@sysoev.ru     }
362240Sigor@sysoev.ru 
3631182St.nateldemoura@f5.com     rt = task->thread->runtime;
3641182St.nateldemoura@f5.com 
3651488St.nateldemoura@f5.com     app_conf->user.start  = (u_char*)rt->user_cred.user;
3661488St.nateldemoura@f5.com     app_conf->user.length = nxt_strlen(rt->user_cred.user);
367240Sigor@sysoev.ru 
3681488St.nateldemoura@f5.com     ret = nxt_conf_map_object(process->mem_pool, conf, nxt_common_app_conf,
3691488St.nateldemoura@f5.com                               nxt_nitems(nxt_common_app_conf), app_conf);
3701488St.nateldemoura@f5.com 
371240Sigor@sysoev.ru     if (ret != NXT_OK) {
372564Svbart@nginx.com         nxt_alert(task, "failed to map common app conf received from router");
373318Smax.romanov@nginx.com         goto failed;
374240Sigor@sysoev.ru     }
375240Sigor@sysoev.ru 
3761488St.nateldemoura@f5.com     for (type_len = 0; type_len != app_conf->type.length; type_len++) {
3771488St.nateldemoura@f5.com         ch = app_conf->type.start[type_len];
378536Svbart@nginx.com 
379536Svbart@nginx.com         if (ch == ' ' || nxt_isdigit(ch)) {
380536Svbart@nginx.com             break;
381536Svbart@nginx.com         }
382536Svbart@nginx.com     }
383536Svbart@nginx.com 
3841488St.nateldemoura@f5.com     idx = nxt_app_parse_type(app_conf->type.start, type_len);
385510Salexander.borisov@nginx.com 
386546Smax.romanov@nginx.com     if (nxt_slow_path(idx >= nxt_nitems(nxt_app_maps))) {
387564Svbart@nginx.com         nxt_alert(task, "invalid app type %d received from router", (int) idx);
388546Smax.romanov@nginx.com         goto failed;
389546Smax.romanov@nginx.com     }
390510Salexander.borisov@nginx.com 
3911488St.nateldemoura@f5.com     ret = nxt_conf_map_object(process->mem_pool, conf, nxt_app_maps[idx].map,
3921488St.nateldemoura@f5.com                               nxt_app_maps[idx].size, app_conf);
393510Salexander.borisov@nginx.com 
394546Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
395564Svbart@nginx.com         nxt_alert(task, "failed to map app conf received from router");
396546Smax.romanov@nginx.com         goto failed;
397546Smax.romanov@nginx.com     }
398510Salexander.borisov@nginx.com 
3991488St.nateldemoura@f5.com     if (app_conf->limits != NULL) {
4001488St.nateldemoura@f5.com         ret = nxt_conf_map_object(process->mem_pool, app_conf->limits,
4011320Smax.romanov@nginx.com                                   nxt_common_app_limits_conf,
4021320Smax.romanov@nginx.com                                   nxt_nitems(nxt_common_app_limits_conf),
4031488St.nateldemoura@f5.com                                   app_conf);
4041320Smax.romanov@nginx.com 
4051320Smax.romanov@nginx.com         if (nxt_slow_path(ret != NXT_OK)) {
4061320Smax.romanov@nginx.com             nxt_alert(task, "failed to map app limits received from router");
4071320Smax.romanov@nginx.com             goto failed;
4081320Smax.romanov@nginx.com         }
4091320Smax.romanov@nginx.com     }
4101320Smax.romanov@nginx.com 
4111488St.nateldemoura@f5.com     app_conf->self = conf;
4121488St.nateldemoura@f5.com 
4131488St.nateldemoura@f5.com     process->stream = msg->port_msg.stream;
4141488St.nateldemoura@f5.com     process->data.app = app_conf;
4151473Svbart@nginx.com 
4161488St.nateldemoura@f5.com     ret = nxt_main_start_process(task, process);
4171488St.nateldemoura@f5.com     if (nxt_fast_path(ret == NXT_OK || ret == NXT_AGAIN)) {
4181488St.nateldemoura@f5.com         return;
4191488St.nateldemoura@f5.com     }
420240Sigor@sysoev.ru 
421318Smax.romanov@nginx.com failed:
422318Smax.romanov@nginx.com 
4231488St.nateldemoura@f5.com     nxt_process_use(task, process, -1);
4241488St.nateldemoura@f5.com 
4251488St.nateldemoura@f5.com     port = nxt_runtime_port_find(rt, msg->port_msg.pid,
4261488St.nateldemoura@f5.com                                  msg->port_msg.reply_port);
4271488St.nateldemoura@f5.com 
4281488St.nateldemoura@f5.com     if (nxt_fast_path(port != NULL)) {
4291488St.nateldemoura@f5.com         nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
4301488St.nateldemoura@f5.com                               -1, msg->port_msg.stream, 0, NULL);
4311488St.nateldemoura@f5.com     }
4321488St.nateldemoura@f5.com }
4331488St.nateldemoura@f5.com 
4341488St.nateldemoura@f5.com 
4351488St.nateldemoura@f5.com static void
4361488St.nateldemoura@f5.com nxt_main_process_created_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
4371488St.nateldemoura@f5.com {
4381488St.nateldemoura@f5.com     nxt_port_t     *port;
4391488St.nateldemoura@f5.com     nxt_process_t  *process;
4401488St.nateldemoura@f5.com     nxt_runtime_t  *rt;
4411488St.nateldemoura@f5.com 
4421488St.nateldemoura@f5.com     rt = task->thread->runtime;
4431488St.nateldemoura@f5.com 
4441488St.nateldemoura@f5.com     process = nxt_runtime_process_find(rt, msg->port_msg.pid);
4451488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
4461488St.nateldemoura@f5.com         return;
447318Smax.romanov@nginx.com     }
448318Smax.romanov@nginx.com 
4491488St.nateldemoura@f5.com     nxt_assert(process->state == NXT_PROCESS_STATE_CREATING);
4501488St.nateldemoura@f5.com 
4511488St.nateldemoura@f5.com     port = nxt_runtime_port_find(rt, msg->port_msg.pid,
4521488St.nateldemoura@f5.com                                  msg->port_msg.reply_port);
4531488St.nateldemoura@f5.com 
4541488St.nateldemoura@f5.com 
4551488St.nateldemoura@f5.com     if (nxt_slow_path(port == NULL)) {
4561488St.nateldemoura@f5.com         return;
4571488St.nateldemoura@f5.com     }
4581488St.nateldemoura@f5.com 
4591488St.nateldemoura@f5.com #if (NXT_HAVE_CLONE && NXT_HAVE_CLONE_NEWUSER)
4601488St.nateldemoura@f5.com     if (nxt_is_clone_flag_set(process->isolation.clone.flags, NEWUSER)) {
4611488St.nateldemoura@f5.com         if (nxt_slow_path(nxt_clone_credential_map(task, process->pid,
4621488St.nateldemoura@f5.com                                                    process->user_cred,
4631488St.nateldemoura@f5.com                                                    &process->isolation.clone)
4641488St.nateldemoura@f5.com                           != NXT_OK))
4651488St.nateldemoura@f5.com         {
4661488St.nateldemoura@f5.com             (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR,
4671488St.nateldemoura@f5.com                                          -1, msg->port_msg.stream, 0, NULL);
4681488St.nateldemoura@f5.com             return;
4691488St.nateldemoura@f5.com         }
4701488St.nateldemoura@f5.com      }
4711488St.nateldemoura@f5.com 
4721488St.nateldemoura@f5.com #endif
4731488St.nateldemoura@f5.com 
4741488St.nateldemoura@f5.com     process->state = NXT_PROCESS_STATE_CREATED;
4751488St.nateldemoura@f5.com 
4761488St.nateldemoura@f5.com     (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_READY_LAST,
4771488St.nateldemoura@f5.com                                  -1, msg->port_msg.stream, 0, NULL);
478240Sigor@sysoev.ru }
479240Sigor@sysoev.ru 
480240Sigor@sysoev.ru 
481320Smax.romanov@nginx.com static nxt_port_handlers_t  nxt_main_process_port_handlers = {
4821488St.nateldemoura@f5.com     .data             = nxt_port_main_data_handler,
4831488St.nateldemoura@f5.com     .process_created  = nxt_main_process_created_handler,
4841488St.nateldemoura@f5.com     .process_ready    = nxt_port_process_ready_handler,
4851488St.nateldemoura@f5.com     .start_process    = nxt_port_main_start_process_handler,
4861488St.nateldemoura@f5.com     .socket           = nxt_main_port_socket_handler,
4871488St.nateldemoura@f5.com     .modules          = nxt_main_port_modules_handler,
4881488St.nateldemoura@f5.com     .conf_store       = nxt_main_port_conf_store_handler,
489774Svbart@nginx.com #if (NXT_TLS)
4901488St.nateldemoura@f5.com     .cert_get         = nxt_cert_store_get_handler,
4911488St.nateldemoura@f5.com     .cert_delete      = nxt_cert_store_delete_handler,
492774Svbart@nginx.com #endif
4931488St.nateldemoura@f5.com     .access_log       = nxt_main_port_access_log_handler,
4941488St.nateldemoura@f5.com     .rpc_ready        = nxt_port_rpc_handler,
4951488St.nateldemoura@f5.com     .rpc_error        = nxt_port_rpc_handler,
496240Sigor@sysoev.ru };
497240Sigor@sysoev.ru 
498240Sigor@sysoev.ru 
499240Sigor@sysoev.ru static nxt_int_t
500240Sigor@sysoev.ru nxt_main_process_port_create(nxt_task_t *task, nxt_runtime_t *rt)
501240Sigor@sysoev.ru {
502240Sigor@sysoev.ru     nxt_int_t      ret;
503240Sigor@sysoev.ru     nxt_port_t     *port;
504240Sigor@sysoev.ru     nxt_process_t  *process;
505240Sigor@sysoev.ru 
5061254Shongzhidao@gmail.com     port = nxt_runtime_process_port_create(task, rt, nxt_pid, 0,
5071254Shongzhidao@gmail.com                                            NXT_PROCESS_MAIN);
508240Sigor@sysoev.ru     if (nxt_slow_path(port == NULL)) {
509240Sigor@sysoev.ru         return NXT_ERROR;
510240Sigor@sysoev.ru     }
511240Sigor@sysoev.ru 
5121254Shongzhidao@gmail.com     process = port->process;
513349Smax.romanov@nginx.com 
514240Sigor@sysoev.ru     ret = nxt_port_socket_init(task, port, 0);
515240Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
5161488St.nateldemoura@f5.com         nxt_port_use(task, port, -1);
517240Sigor@sysoev.ru         return ret;
518240Sigor@sysoev.ru     }
519240Sigor@sysoev.ru 
520240Sigor@sysoev.ru     /*
521240Sigor@sysoev.ru      * A main process port.  A write port is not closed
5221488St.nateldemoura@f5.com      * since it should be inherited by processes.
523240Sigor@sysoev.ru      */
524320Smax.romanov@nginx.com     nxt_port_enable(task, port, &nxt_main_process_port_handlers);
525240Sigor@sysoev.ru 
5261488St.nateldemoura@f5.com     process->state = NXT_PROCESS_STATE_READY;
527240Sigor@sysoev.ru 
528240Sigor@sysoev.ru     return NXT_OK;
529240Sigor@sysoev.ru }
530240Sigor@sysoev.ru 
531240Sigor@sysoev.ru 
532240Sigor@sysoev.ru static void
533240Sigor@sysoev.ru nxt_main_process_title(nxt_task_t *task)
534240Sigor@sysoev.ru {
535240Sigor@sysoev.ru     u_char      *p, *end;
536240Sigor@sysoev.ru     nxt_uint_t  i;
537240Sigor@sysoev.ru     u_char      title[2048];
538240Sigor@sysoev.ru 
539240Sigor@sysoev.ru     end = title + sizeof(title) - 1;
540240Sigor@sysoev.ru 
541680Sigor@sysoev.ru     p = nxt_sprintf(title, end, "unit: main v" NXT_VERSION " [%s",
542680Sigor@sysoev.ru                     nxt_process_argv[0]);
543240Sigor@sysoev.ru 
544240Sigor@sysoev.ru     for (i = 1; nxt_process_argv[i] != NULL; i++) {
545240Sigor@sysoev.ru         p = nxt_sprintf(p, end, " %s", nxt_process_argv[i]);
546240Sigor@sysoev.ru     }
547240Sigor@sysoev.ru 
548240Sigor@sysoev.ru     if (p < end) {
549240Sigor@sysoev.ru         *p++ = ']';
550240Sigor@sysoev.ru     }
551240Sigor@sysoev.ru 
552240Sigor@sysoev.ru     *p = '\0';
553240Sigor@sysoev.ru 
554240Sigor@sysoev.ru     nxt_process_title(task, "%s", title);
555240Sigor@sysoev.ru }
556240Sigor@sysoev.ru 
557240Sigor@sysoev.ru 
558240Sigor@sysoev.ru static nxt_int_t
5591488St.nateldemoura@f5.com nxt_main_process_create(nxt_task_t *task, const nxt_process_init_t init)
560240Sigor@sysoev.ru {
5611488St.nateldemoura@f5.com     nxt_int_t           ret;
5621488St.nateldemoura@f5.com     nxt_runtime_t       *rt;
5631488St.nateldemoura@f5.com     nxt_process_t       *process;
5641488St.nateldemoura@f5.com     nxt_process_init_t  *pinit;
565240Sigor@sysoev.ru 
5661488St.nateldemoura@f5.com     rt = task->thread->runtime;
5671302St.nateldemoura@f5.com 
5681488St.nateldemoura@f5.com     process = nxt_main_process_new(task, rt);
5691488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
570368Svbart@nginx.com         return NXT_ERROR;
571368Svbart@nginx.com     }
572368Svbart@nginx.com 
5731488St.nateldemoura@f5.com     process->name = init.name;
5741488St.nateldemoura@f5.com     process->user_cred = &rt->user_cred;
575314Svbart@nginx.com 
5761488St.nateldemoura@f5.com     pinit = nxt_process_init(process);
5771488St.nateldemoura@f5.com     *pinit = init;
578314Svbart@nginx.com 
5791488St.nateldemoura@f5.com     ret = nxt_main_start_process(task, process);
5801488St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
5811488St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
582314Svbart@nginx.com     }
583314Svbart@nginx.com 
584314Svbart@nginx.com     return ret;
585240Sigor@sysoev.ru }
586240Sigor@sysoev.ru 
587240Sigor@sysoev.ru 
5881488St.nateldemoura@f5.com static nxt_process_t *
5891488St.nateldemoura@f5.com nxt_main_process_new(nxt_task_t *task, nxt_runtime_t *rt)
590240Sigor@sysoev.ru {
5911488St.nateldemoura@f5.com     nxt_process_t  *process;
592240Sigor@sysoev.ru 
5931488St.nateldemoura@f5.com     process = nxt_runtime_process_new(rt);
5941488St.nateldemoura@f5.com     if (nxt_slow_path(process == NULL)) {
5951488St.nateldemoura@f5.com         return NULL;
596240Sigor@sysoev.ru     }
597240Sigor@sysoev.ru 
5981488St.nateldemoura@f5.com     process->mem_pool = nxt_mp_create(1024, 128, 256, 32);
5991488St.nateldemoura@f5.com     if (process->mem_pool == NULL) {
6001488St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6011488St.nateldemoura@f5.com         return NULL;
602240Sigor@sysoev.ru     }
603240Sigor@sysoev.ru 
6041488St.nateldemoura@f5.com     return process;
605240Sigor@sysoev.ru }
606240Sigor@sysoev.ru 
6071302St.nateldemoura@f5.com 
608240Sigor@sysoev.ru static nxt_int_t
6091488St.nateldemoura@f5.com nxt_main_start_process(nxt_task_t *task, nxt_process_t *process)
610240Sigor@sysoev.ru {
6111488St.nateldemoura@f5.com     nxt_mp_t            *tmp_mp;
6121182St.nateldemoura@f5.com     nxt_int_t           ret;
6131488St.nateldemoura@f5.com     nxt_pid_t           pid;
6141488St.nateldemoura@f5.com     nxt_port_t          *port;
615240Sigor@sysoev.ru     nxt_process_init_t  *init;
616240Sigor@sysoev.ru 
6171488St.nateldemoura@f5.com     init = nxt_process_init(process);
618240Sigor@sysoev.ru 
619240Sigor@sysoev.ru     port = nxt_port_new(task, 0, 0, init->type);
620240Sigor@sysoev.ru     if (nxt_slow_path(port == NULL)) {
621240Sigor@sysoev.ru         return NXT_ERROR;
622240Sigor@sysoev.ru     }
623240Sigor@sysoev.ru 
624240Sigor@sysoev.ru     nxt_process_port_add(task, process, port);
625240Sigor@sysoev.ru 
626240Sigor@sysoev.ru     ret = nxt_port_socket_init(task, port, 0);
627240Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
6281565St.nateldemoura@f5.com         goto free_port;
6291488St.nateldemoura@f5.com     }
6301488St.nateldemoura@f5.com 
6311488St.nateldemoura@f5.com     tmp_mp = nxt_mp_create(1024, 128, 256, 32);
6321565St.nateldemoura@f5.com     if (nxt_slow_path(tmp_mp == NULL)) {
6331565St.nateldemoura@f5.com         ret = NXT_ERROR;
6341565St.nateldemoura@f5.com 
6351565St.nateldemoura@f5.com         goto close_port;
6361488St.nateldemoura@f5.com     }
6371488St.nateldemoura@f5.com 
6381488St.nateldemoura@f5.com     if (init->prefork) {
6391488St.nateldemoura@f5.com         ret = init->prefork(task, process, tmp_mp);
6401488St.nateldemoura@f5.com         if (nxt_slow_path(ret != NXT_OK)) {
6411565St.nateldemoura@f5.com             goto free_mempool;
6421488St.nateldemoura@f5.com         }
643240Sigor@sysoev.ru     }
644240Sigor@sysoev.ru 
645240Sigor@sysoev.ru     pid = nxt_process_create(task, process);
646240Sigor@sysoev.ru 
647240Sigor@sysoev.ru     switch (pid) {
648240Sigor@sysoev.ru 
649240Sigor@sysoev.ru     case -1:
6501565St.nateldemoura@f5.com         ret = NXT_ERROR;
6511488St.nateldemoura@f5.com         break;
652240Sigor@sysoev.ru 
653240Sigor@sysoev.ru     case 0:
6541488St.nateldemoura@f5.com         /* The child process: return to the event engine work queue loop. */
6551180Smax.romanov@nginx.com 
6561565St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6571565St.nateldemoura@f5.com 
6581488St.nateldemoura@f5.com         ret = NXT_AGAIN;
6591488St.nateldemoura@f5.com         break;
660240Sigor@sysoev.ru 
661240Sigor@sysoev.ru     default:
662240Sigor@sysoev.ru         /* The main process created a new process. */
663240Sigor@sysoev.ru 
6641565St.nateldemoura@f5.com         nxt_process_use(task, process, -1);
6651565St.nateldemoura@f5.com 
666240Sigor@sysoev.ru         nxt_port_read_close(port);
667240Sigor@sysoev.ru         nxt_port_write_enable(task, port);
668240Sigor@sysoev.ru 
6691488St.nateldemoura@f5.com         ret = NXT_OK;
6701488St.nateldemoura@f5.com         break;
671240Sigor@sysoev.ru     }
672240Sigor@sysoev.ru 
6731565St.nateldemoura@f5.com free_mempool:
6741565St.nateldemoura@f5.com 
6751565St.nateldemoura@f5.com     nxt_mp_destroy(tmp_mp);
6761565St.nateldemoura@f5.com 
6771565St.nateldemoura@f5.com close_port:
6781565St.nateldemoura@f5.com 
6791565St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
6801565St.nateldemoura@f5.com         nxt_port_close(task, port);
6811565St.nateldemoura@f5.com     }
6821565St.nateldemoura@f5.com 
6831565St.nateldemoura@f5.com free_port:
684240Sigor@sysoev.ru 
6851488St.nateldemoura@f5.com     nxt_port_use(task, port, -1);
686240Sigor@sysoev.ru 
6871488St.nateldemoura@f5.com     return ret;
688240Sigor@sysoev.ru }
689240Sigor@sysoev.ru 
690240Sigor@sysoev.ru 
691240Sigor@sysoev.ru static void
692240Sigor@sysoev.ru nxt_main_process_sigterm_handler(nxt_task_t *task, void *obj, void *data)
693240Sigor@sysoev.ru {
694240Sigor@sysoev.ru     nxt_debug(task, "sigterm handler signo:%d (%s)",
695240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
696240Sigor@sysoev.ru 
697240Sigor@sysoev.ru     /* TODO: fast exit. */
698240Sigor@sysoev.ru 
699240Sigor@sysoev.ru     nxt_exiting = 1;
700240Sigor@sysoev.ru 
701697Sigor@sysoev.ru     nxt_runtime_quit(task, 0);
702240Sigor@sysoev.ru }
703240Sigor@sysoev.ru 
704240Sigor@sysoev.ru 
705240Sigor@sysoev.ru static void
706240Sigor@sysoev.ru nxt_main_process_sigquit_handler(nxt_task_t *task, void *obj, void *data)
707240Sigor@sysoev.ru {
708240Sigor@sysoev.ru     nxt_debug(task, "sigquit handler signo:%d (%s)",
709240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
710240Sigor@sysoev.ru 
711240Sigor@sysoev.ru     /* TODO: graceful exit. */
712240Sigor@sysoev.ru 
713240Sigor@sysoev.ru     nxt_exiting = 1;
714240Sigor@sysoev.ru 
715697Sigor@sysoev.ru     nxt_runtime_quit(task, 0);
716240Sigor@sysoev.ru }
717240Sigor@sysoev.ru 
718240Sigor@sysoev.ru 
719240Sigor@sysoev.ru static void
720240Sigor@sysoev.ru nxt_main_process_sigusr1_handler(nxt_task_t *task, void *obj, void *data)
721240Sigor@sysoev.ru {
722240Sigor@sysoev.ru     nxt_mp_t        *mp;
723240Sigor@sysoev.ru     nxt_int_t       ret;
724240Sigor@sysoev.ru     nxt_uint_t      n;
725631Svbart@nginx.com     nxt_port_t      *port;
726240Sigor@sysoev.ru     nxt_file_t      *file, *new_file;
727631Svbart@nginx.com     nxt_array_t     *new_files;
728240Sigor@sysoev.ru     nxt_runtime_t   *rt;
729240Sigor@sysoev.ru 
730240Sigor@sysoev.ru     nxt_log(task, NXT_LOG_NOTICE, "signal %d (%s) recevied, %s",
731240Sigor@sysoev.ru             (int) (uintptr_t) obj, data, "log files rotation");
732240Sigor@sysoev.ru 
733631Svbart@nginx.com     rt = task->thread->runtime;
734631Svbart@nginx.com 
735631Svbart@nginx.com     port = rt->port_by_type[NXT_PROCESS_ROUTER];
736631Svbart@nginx.com 
737631Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
738631Svbart@nginx.com         (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_ACCESS_LOG,
739631Svbart@nginx.com                                      -1, 0, 0, NULL);
740631Svbart@nginx.com     }
741631Svbart@nginx.com 
742240Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
743240Sigor@sysoev.ru     if (mp == NULL) {
744240Sigor@sysoev.ru         return;
745240Sigor@sysoev.ru     }
746240Sigor@sysoev.ru 
747240Sigor@sysoev.ru     n = nxt_list_nelts(rt->log_files);
748240Sigor@sysoev.ru 
749240Sigor@sysoev.ru     new_files = nxt_array_create(mp, n, sizeof(nxt_file_t));
750240Sigor@sysoev.ru     if (new_files == NULL) {
751240Sigor@sysoev.ru         nxt_mp_destroy(mp);
752240Sigor@sysoev.ru         return;
753240Sigor@sysoev.ru     }
754240Sigor@sysoev.ru 
755240Sigor@sysoev.ru     nxt_list_each(file, rt->log_files) {
756240Sigor@sysoev.ru 
757240Sigor@sysoev.ru         /* This allocation cannot fail. */
758240Sigor@sysoev.ru         new_file = nxt_array_add(new_files);
759240Sigor@sysoev.ru 
760240Sigor@sysoev.ru         new_file->name = file->name;
761240Sigor@sysoev.ru         new_file->fd = NXT_FILE_INVALID;
762564Svbart@nginx.com         new_file->log_level = NXT_LOG_ALERT;
763240Sigor@sysoev.ru 
764240Sigor@sysoev.ru         ret = nxt_file_open(task, new_file, O_WRONLY | O_APPEND, O_CREAT,
765240Sigor@sysoev.ru                             NXT_FILE_OWNER_ACCESS);
766240Sigor@sysoev.ru 
767240Sigor@sysoev.ru         if (ret != NXT_OK) {
768240Sigor@sysoev.ru             goto fail;
769240Sigor@sysoev.ru         }
770240Sigor@sysoev.ru 
771240Sigor@sysoev.ru     } nxt_list_loop;
772240Sigor@sysoev.ru 
773240Sigor@sysoev.ru     new_file = new_files->elts;
774240Sigor@sysoev.ru 
775240Sigor@sysoev.ru     ret = nxt_file_stderr(&new_file[0]);
776240Sigor@sysoev.ru 
777240Sigor@sysoev.ru     if (ret == NXT_OK) {
778240Sigor@sysoev.ru         n = 0;
779240Sigor@sysoev.ru 
780240Sigor@sysoev.ru         nxt_list_each(file, rt->log_files) {
781240Sigor@sysoev.ru 
782240Sigor@sysoev.ru             nxt_port_change_log_file(task, rt, n, new_file[n].fd);
783240Sigor@sysoev.ru             /*
784240Sigor@sysoev.ru              * The old log file descriptor must be closed at the moment
785240Sigor@sysoev.ru              * when no other threads use it.  dup2() allows to use the
786240Sigor@sysoev.ru              * old file descriptor for new log file.  This change is
787240Sigor@sysoev.ru              * performed atomically in the kernel.
788240Sigor@sysoev.ru              */
789240Sigor@sysoev.ru             (void) nxt_file_redirect(file, new_file[n].fd);
790240Sigor@sysoev.ru 
791240Sigor@sysoev.ru             n++;
792240Sigor@sysoev.ru 
793240Sigor@sysoev.ru         } nxt_list_loop;
794240Sigor@sysoev.ru 
795240Sigor@sysoev.ru         nxt_mp_destroy(mp);
796240Sigor@sysoev.ru         return;
7971008Szelenkov@nginx.com     }
798240Sigor@sysoev.ru 
799240Sigor@sysoev.ru fail:
800240Sigor@sysoev.ru 
801240Sigor@sysoev.ru     new_file = new_files->elts;
802240Sigor@sysoev.ru     n = new_files->nelts;
803240Sigor@sysoev.ru 
804240Sigor@sysoev.ru     while (n != 0) {
805240Sigor@sysoev.ru         if (new_file->fd != NXT_FILE_INVALID) {
806240Sigor@sysoev.ru             nxt_file_close(task, new_file);
807240Sigor@sysoev.ru         }
808240Sigor@sysoev.ru 
809240Sigor@sysoev.ru         new_file++;
810240Sigor@sysoev.ru         n--;
811240Sigor@sysoev.ru     }
812240Sigor@sysoev.ru 
813240Sigor@sysoev.ru     nxt_mp_destroy(mp);
814240Sigor@sysoev.ru }
815240Sigor@sysoev.ru 
816240Sigor@sysoev.ru 
817240Sigor@sysoev.ru static void
818240Sigor@sysoev.ru nxt_main_process_sigchld_handler(nxt_task_t *task, void *obj, void *data)
819240Sigor@sysoev.ru {
820240Sigor@sysoev.ru     int                    status;
821240Sigor@sysoev.ru     nxt_err_t              err;
822240Sigor@sysoev.ru     nxt_pid_t              pid;
823240Sigor@sysoev.ru 
824240Sigor@sysoev.ru     nxt_debug(task, "sigchld handler signo:%d (%s)",
825240Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
826240Sigor@sysoev.ru 
827240Sigor@sysoev.ru     for ( ;; ) {
828240Sigor@sysoev.ru         pid = waitpid(-1, &status, WNOHANG);
829240Sigor@sysoev.ru 
830240Sigor@sysoev.ru         if (pid == -1) {
831240Sigor@sysoev.ru 
832240Sigor@sysoev.ru             switch (err = nxt_errno) {
833240Sigor@sysoev.ru 
834240Sigor@sysoev.ru             case NXT_ECHILD:
835240Sigor@sysoev.ru                 return;
836240Sigor@sysoev.ru 
837240Sigor@sysoev.ru             case NXT_EINTR:
838240Sigor@sysoev.ru                 continue;
839240Sigor@sysoev.ru 
840240Sigor@sysoev.ru             default:
841564Svbart@nginx.com                 nxt_alert(task, "waitpid() failed: %E", err);
842240Sigor@sysoev.ru                 return;
843240Sigor@sysoev.ru             }
844240Sigor@sysoev.ru         }
845240Sigor@sysoev.ru 
846240Sigor@sysoev.ru         nxt_debug(task, "waitpid(): %PI", pid);
847240Sigor@sysoev.ru 
848240Sigor@sysoev.ru         if (pid == 0) {
849240Sigor@sysoev.ru             return;
850240Sigor@sysoev.ru         }
851240Sigor@sysoev.ru 
852240Sigor@sysoev.ru         if (WTERMSIG(status)) {
853240Sigor@sysoev.ru #ifdef WCOREDUMP
854564Svbart@nginx.com             nxt_alert(task, "process %PI exited on signal %d%s",
855564Svbart@nginx.com                       pid, WTERMSIG(status),
856564Svbart@nginx.com                       WCOREDUMP(status) ? " (core dumped)" : "");
857240Sigor@sysoev.ru #else
858564Svbart@nginx.com             nxt_alert(task, "process %PI exited on signal %d",
859564Svbart@nginx.com                       pid, WTERMSIG(status));
860240Sigor@sysoev.ru #endif
861240Sigor@sysoev.ru 
862240Sigor@sysoev.ru         } else {
863240Sigor@sysoev.ru             nxt_trace(task, "process %PI exited with code %d",
864240Sigor@sysoev.ru                       pid, WEXITSTATUS(status));
865240Sigor@sysoev.ru         }
866240Sigor@sysoev.ru 
8671488St.nateldemoura@f5.com         nxt_main_cleanup_process(task, pid);
868240Sigor@sysoev.ru     }
869240Sigor@sysoev.ru }
870240Sigor@sysoev.ru 
871240Sigor@sysoev.ru 
872240Sigor@sysoev.ru static void
873944Sigor@sysoev.ru nxt_main_process_signal_handler(nxt_task_t *task, void *obj, void *data)
874944Sigor@sysoev.ru {
875944Sigor@sysoev.ru     nxt_trace(task, "signal signo:%d (%s) recevied, ignored",
876944Sigor@sysoev.ru               (int) (uintptr_t) obj, data);
877944Sigor@sysoev.ru }
878944Sigor@sysoev.ru 
879944Sigor@sysoev.ru 
880944Sigor@sysoev.ru static void
8811488St.nateldemoura@f5.com nxt_main_cleanup_process(nxt_task_t *task, nxt_pid_t pid)
882240Sigor@sysoev.ru {
8831488St.nateldemoura@f5.com     int                 stream;
8841488St.nateldemoura@f5.com     nxt_int_t           ret;
8851488St.nateldemoura@f5.com     nxt_buf_t           *buf;
8861488St.nateldemoura@f5.com     nxt_port_t          *port;
8871488St.nateldemoura@f5.com     const char          *name;
8881488St.nateldemoura@f5.com     nxt_runtime_t       *rt;
8891488St.nateldemoura@f5.com     nxt_process_t       *process;
8901488St.nateldemoura@f5.com     nxt_process_init_t  init;
891240Sigor@sysoev.ru 
892240Sigor@sysoev.ru     rt = task->thread->runtime;
893240Sigor@sysoev.ru 
894240Sigor@sysoev.ru     process = nxt_runtime_process_find(rt, pid);
8951488St.nateldemoura@f5.com     if (!process) {
8961488St.nateldemoura@f5.com         return;
8971488St.nateldemoura@f5.com     }
898240Sigor@sysoev.ru 
8991579St.nateldemoura@f5.com     if (process->isolation.cleanup != NULL) {
9001579St.nateldemoura@f5.com         process->isolation.cleanup(task, process);
9011489St.nateldemoura@f5.com     }
9021489St.nateldemoura@f5.com 
9031488St.nateldemoura@f5.com     name = process->name;
9041488St.nateldemoura@f5.com     stream = process->stream;
9051488St.nateldemoura@f5.com     init = *((nxt_process_init_t *) nxt_process_init(process));
906366Smax.romanov@nginx.com 
9071488St.nateldemoura@f5.com     if (process->state == NXT_PROCESS_STATE_READY) {
9081488St.nateldemoura@f5.com         process->stream = 0;
9091488St.nateldemoura@f5.com     }
910240Sigor@sysoev.ru 
9111488St.nateldemoura@f5.com     nxt_process_close_ports(task, process);
9121302St.nateldemoura@f5.com 
9131488St.nateldemoura@f5.com     if (nxt_exiting) {
9141488St.nateldemoura@f5.com         if (rt->nprocesses <= 1) {
9151488St.nateldemoura@f5.com             nxt_runtime_quit(task, 0);
9161211Smax.romanov@nginx.com         }
9171211Smax.romanov@nginx.com 
9181488St.nateldemoura@f5.com         return;
919240Sigor@sysoev.ru     }
920754Smax.romanov@nginx.com 
921754Smax.romanov@nginx.com     nxt_runtime_process_each(rt, process) {
922754Smax.romanov@nginx.com 
9231488St.nateldemoura@f5.com         if (process->pid == nxt_pid
9241488St.nateldemoura@f5.com             || process->pid == pid
9251488St.nateldemoura@f5.com             || nxt_queue_is_empty(&process->ports))
9261488St.nateldemoura@f5.com         {
9271488St.nateldemoura@f5.com             continue;
9281488St.nateldemoura@f5.com         }
9291488St.nateldemoura@f5.com 
9301488St.nateldemoura@f5.com         port = nxt_process_port_first(process);
931754Smax.romanov@nginx.com 
9321488St.nateldemoura@f5.com         if (nxt_proc_remove_notify_matrix[init.type][port->type] == 0) {
9331488St.nateldemoura@f5.com             continue;
9341488St.nateldemoura@f5.com         }
9351488St.nateldemoura@f5.com 
9361488St.nateldemoura@f5.com         buf = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
9371488St.nateldemoura@f5.com                                    sizeof(pid));
938754Smax.romanov@nginx.com 
9391488St.nateldemoura@f5.com         if (nxt_slow_path(buf == NULL)) {
9401488St.nateldemoura@f5.com             continue;
9411488St.nateldemoura@f5.com         }
9421488St.nateldemoura@f5.com 
9431488St.nateldemoura@f5.com         buf->mem.free = nxt_cpymem(buf->mem.free, &pid, sizeof(pid));
9441488St.nateldemoura@f5.com 
9451488St.nateldemoura@f5.com         nxt_port_socket_write(task, port, NXT_PORT_MSG_REMOVE_PID, -1,
9461488St.nateldemoura@f5.com                               stream, 0, buf);
947754Smax.romanov@nginx.com 
948754Smax.romanov@nginx.com     } nxt_runtime_process_loop;
9491488St.nateldemoura@f5.com 
9501488St.nateldemoura@f5.com     if (init.restart) {
9511488St.nateldemoura@f5.com         ret = nxt_main_process_create(task, init);
9521488St.nateldemoura@f5.com         if (nxt_slow_path(ret == NXT_ERROR)) {
9531488St.nateldemoura@f5.com             nxt_alert(task, "failed to restart %s", name);
9541488St.nateldemoura@f5.com         }
9551488St.nateldemoura@f5.com     }
956754Smax.romanov@nginx.com }
957754Smax.romanov@nginx.com 
958754Smax.romanov@nginx.com 
959754Smax.romanov@nginx.com static void
960240Sigor@sysoev.ru nxt_main_port_socket_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
961240Sigor@sysoev.ru {
962240Sigor@sysoev.ru     size_t                  size;
963240Sigor@sysoev.ru     nxt_int_t               ret;
964240Sigor@sysoev.ru     nxt_buf_t               *b, *out;
965240Sigor@sysoev.ru     nxt_port_t              *port;
966240Sigor@sysoev.ru     nxt_sockaddr_t          *sa;
967240Sigor@sysoev.ru     nxt_port_msg_type_t     type;
968240Sigor@sysoev.ru     nxt_listening_socket_t  ls;
969240Sigor@sysoev.ru     u_char                  message[2048];
970240Sigor@sysoev.ru 
971240Sigor@sysoev.ru     b = msg->buf;
972240Sigor@sysoev.ru     sa = (nxt_sockaddr_t *) b->mem.pos;
973240Sigor@sysoev.ru 
974352Smax.romanov@nginx.com     /* TODO check b size and make plain */
975352Smax.romanov@nginx.com 
976240Sigor@sysoev.ru     out = NULL;
977240Sigor@sysoev.ru 
978240Sigor@sysoev.ru     ls.socket = -1;
979240Sigor@sysoev.ru     ls.error = NXT_SOCKET_ERROR_SYSTEM;
980240Sigor@sysoev.ru     ls.start = message;
981240Sigor@sysoev.ru     ls.end = message + sizeof(message);
982240Sigor@sysoev.ru 
983240Sigor@sysoev.ru     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
984240Sigor@sysoev.ru                                  msg->port_msg.reply_port);
985240Sigor@sysoev.ru 
986240Sigor@sysoev.ru     nxt_debug(task, "listening socket \"%*s\"",
987493Spluknet@nginx.com               (size_t) sa->length, nxt_sockaddr_start(sa));
988240Sigor@sysoev.ru 
989240Sigor@sysoev.ru     ret = nxt_main_listening_socket(sa, &ls);
990240Sigor@sysoev.ru 
991240Sigor@sysoev.ru     if (ret == NXT_OK) {
992240Sigor@sysoev.ru         nxt_debug(task, "socket(\"%*s\"): %d",
993493Spluknet@nginx.com                   (size_t) sa->length, nxt_sockaddr_start(sa), ls.socket);
994240Sigor@sysoev.ru 
995240Sigor@sysoev.ru         type = NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD;
996240Sigor@sysoev.ru 
997240Sigor@sysoev.ru     } else {
998240Sigor@sysoev.ru         size = ls.end - ls.start;
999240Sigor@sysoev.ru 
1000564Svbart@nginx.com         nxt_alert(task, "%*s", size, ls.start);
1001240Sigor@sysoev.ru 
1002342Smax.romanov@nginx.com         out = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool,
1003342Smax.romanov@nginx.com                                    size + 1);
1004240Sigor@sysoev.ru         if (nxt_slow_path(out == NULL)) {
1005240Sigor@sysoev.ru             return;
1006240Sigor@sysoev.ru         }
1007240Sigor@sysoev.ru 
1008240Sigor@sysoev.ru         *out->mem.free++ = (uint8_t) ls.error;
1009240Sigor@sysoev.ru 
1010240Sigor@sysoev.ru         out->mem.free = nxt_cpymem(out->mem.free, ls.start, size);
1011240Sigor@sysoev.ru 
1012240Sigor@sysoev.ru         type = NXT_PORT_MSG_RPC_ERROR;
1013240Sigor@sysoev.ru     }
1014240Sigor@sysoev.ru 
1015240Sigor@sysoev.ru     nxt_port_socket_write(task, port, type, ls.socket, msg->port_msg.stream,
1016240Sigor@sysoev.ru                           0, out);
1017240Sigor@sysoev.ru }
1018240Sigor@sysoev.ru 
1019240Sigor@sysoev.ru 
1020240Sigor@sysoev.ru static nxt_int_t
1021240Sigor@sysoev.ru nxt_main_listening_socket(nxt_sockaddr_t *sa, nxt_listening_socket_t *ls)
1022240Sigor@sysoev.ru {
1023240Sigor@sysoev.ru     nxt_err_t         err;
1024240Sigor@sysoev.ru     nxt_socket_t      s;
1025240Sigor@sysoev.ru 
1026240Sigor@sysoev.ru     const socklen_t   length = sizeof(int);
1027240Sigor@sysoev.ru     static const int  enable = 1;
1028240Sigor@sysoev.ru 
1029240Sigor@sysoev.ru     s = socket(sa->u.sockaddr.sa_family, sa->type, 0);
1030240Sigor@sysoev.ru 
1031240Sigor@sysoev.ru     if (nxt_slow_path(s == -1)) {
1032240Sigor@sysoev.ru         err = nxt_errno;
1033240Sigor@sysoev.ru 
1034240Sigor@sysoev.ru #if (NXT_INET6)
1035240Sigor@sysoev.ru 
1036240Sigor@sysoev.ru         if (err == EAFNOSUPPORT && sa->u.sockaddr.sa_family == AF_INET6) {
1037240Sigor@sysoev.ru             ls->error = NXT_SOCKET_ERROR_NOINET6;
1038240Sigor@sysoev.ru         }
1039240Sigor@sysoev.ru 
1040240Sigor@sysoev.ru #endif
1041240Sigor@sysoev.ru 
1042240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end,
1043240Sigor@sysoev.ru                               "socket(\\\"%*s\\\") failed %E",
1044493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa), err);
1045240Sigor@sysoev.ru 
1046240Sigor@sysoev.ru         return NXT_ERROR;
1047240Sigor@sysoev.ru     }
1048240Sigor@sysoev.ru 
1049240Sigor@sysoev.ru     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &enable, length) != 0) {
1050240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end,
1051240Sigor@sysoev.ru                               "setsockopt(\\\"%*s\\\", SO_REUSEADDR) failed %E",
1052493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa),
1053493Spluknet@nginx.com                               nxt_errno);
1054240Sigor@sysoev.ru         goto fail;
1055240Sigor@sysoev.ru     }
1056240Sigor@sysoev.ru 
1057240Sigor@sysoev.ru #if (NXT_INET6)
1058240Sigor@sysoev.ru 
1059240Sigor@sysoev.ru     if (sa->u.sockaddr.sa_family == AF_INET6) {
1060240Sigor@sysoev.ru 
1061240Sigor@sysoev.ru         if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &enable, length) != 0) {
1062240Sigor@sysoev.ru             ls->end = nxt_sprintf(ls->start, ls->end,
1063240Sigor@sysoev.ru                                "setsockopt(\\\"%*s\\\", IPV6_V6ONLY) failed %E",
1064493Spluknet@nginx.com                                (size_t) sa->length, nxt_sockaddr_start(sa),
1065493Spluknet@nginx.com                                nxt_errno);
1066240Sigor@sysoev.ru             goto fail;
1067240Sigor@sysoev.ru         }
1068240Sigor@sysoev.ru     }
1069240Sigor@sysoev.ru 
1070240Sigor@sysoev.ru #endif
1071240Sigor@sysoev.ru 
1072240Sigor@sysoev.ru     if (bind(s, &sa->u.sockaddr, sa->socklen) != 0) {
1073240Sigor@sysoev.ru         err = nxt_errno;
1074240Sigor@sysoev.ru 
1075240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
1076240Sigor@sysoev.ru 
1077240Sigor@sysoev.ru         if (sa->u.sockaddr.sa_family == AF_UNIX) {
1078240Sigor@sysoev.ru             switch (err) {
1079240Sigor@sysoev.ru 
1080240Sigor@sysoev.ru             case EACCES:
1081240Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_ACCESS;
1082240Sigor@sysoev.ru                 break;
1083240Sigor@sysoev.ru 
1084240Sigor@sysoev.ru             case ENOENT:
1085240Sigor@sysoev.ru             case ENOTDIR:
1086240Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_PATH;
1087240Sigor@sysoev.ru                 break;
1088240Sigor@sysoev.ru             }
1089240Sigor@sysoev.ru 
1090908Sigor@sysoev.ru         } else
1091908Sigor@sysoev.ru #endif
1092908Sigor@sysoev.ru         {
1093908Sigor@sysoev.ru             switch (err) {
1094240Sigor@sysoev.ru 
1095908Sigor@sysoev.ru             case EACCES:
1096908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_PORT;
1097908Sigor@sysoev.ru                 break;
1098240Sigor@sysoev.ru 
1099908Sigor@sysoev.ru             case EADDRINUSE:
1100908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_INUSE;
1101908Sigor@sysoev.ru                 break;
1102240Sigor@sysoev.ru 
1103908Sigor@sysoev.ru             case EADDRNOTAVAIL:
1104908Sigor@sysoev.ru                 ls->error = NXT_SOCKET_ERROR_NOADDR;
1105908Sigor@sysoev.ru                 break;
1106908Sigor@sysoev.ru             }
1107240Sigor@sysoev.ru         }
1108240Sigor@sysoev.ru 
1109240Sigor@sysoev.ru         ls->end = nxt_sprintf(ls->start, ls->end, "bind(\\\"%*s\\\") failed %E",
1110493Spluknet@nginx.com                               (size_t) sa->length, nxt_sockaddr_start(sa), err);
1111240Sigor@sysoev.ru         goto fail;
1112240Sigor@sysoev.ru     }
1113240Sigor@sysoev.ru 
1114240Sigor@sysoev.ru #if (NXT_HAVE_UNIX_DOMAIN)
1115240Sigor@sysoev.ru 
1116240Sigor@sysoev.ru     if (sa->u.sockaddr.sa_family == AF_UNIX) {
1117240Sigor@sysoev.ru         char     *filename;
1118240Sigor@sysoev.ru         mode_t   access;
1119240Sigor@sysoev.ru 
1120240Sigor@sysoev.ru         filename = sa->u.sockaddr_un.sun_path;
1121240Sigor@sysoev.ru         access = (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
1122240Sigor@sysoev.ru 
1123240Sigor@sysoev.ru         if (chmod(filename, access) != 0) {
1124240Sigor@sysoev.ru             ls->end = nxt_sprintf(ls->start, ls->end,
1125494Spluknet@nginx.com                                   "chmod(\\\"%s\\\") failed %E",
1126240Sigor@sysoev.ru                                   filename, nxt_errno);
1127240Sigor@sysoev.ru             goto fail;
1128240Sigor@sysoev.ru         }
1129240Sigor@sysoev.ru     }
1130240Sigor@sysoev.ru 
1131240Sigor@sysoev.ru #endif
1132240Sigor@sysoev.ru 
1133240Sigor@sysoev.ru     ls->socket = s;
1134240Sigor@sysoev.ru 
1135240Sigor@sysoev.ru     return NXT_OK;
1136240Sigor@sysoev.ru 
1137240Sigor@sysoev.ru fail:
1138240Sigor@sysoev.ru 
1139240Sigor@sysoev.ru     (void) close(s);
1140240Sigor@sysoev.ru 
1141240Sigor@sysoev.ru     return NXT_ERROR;
1142240Sigor@sysoev.ru }
1143240Sigor@sysoev.ru 
1144240Sigor@sysoev.ru 
1145240Sigor@sysoev.ru static nxt_conf_map_t  nxt_app_lang_module_map[] = {
1146240Sigor@sysoev.ru     {
1147240Sigor@sysoev.ru         nxt_string("type"),
1148356Svbart@nginx.com         NXT_CONF_MAP_INT,
1149240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, type),
1150240Sigor@sysoev.ru     },
1151240Sigor@sysoev.ru 
1152240Sigor@sysoev.ru     {
1153240Sigor@sysoev.ru         nxt_string("version"),
1154354Svbart@nginx.com         NXT_CONF_MAP_CSTRZ,
1155240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, version),
1156240Sigor@sysoev.ru     },
1157240Sigor@sysoev.ru 
1158240Sigor@sysoev.ru     {
1159240Sigor@sysoev.ru         nxt_string("file"),
1160240Sigor@sysoev.ru         NXT_CONF_MAP_CSTRZ,
1161240Sigor@sysoev.ru         offsetof(nxt_app_lang_module_t, file),
1162240Sigor@sysoev.ru     },
1163240Sigor@sysoev.ru };
1164240Sigor@sysoev.ru 
1165240Sigor@sysoev.ru 
11661489St.nateldemoura@f5.com static nxt_conf_map_t  nxt_app_lang_mounts_map[] = {
11671489St.nateldemoura@f5.com     {
11681489St.nateldemoura@f5.com         nxt_string("src"),
11691489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
11701489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, src),
11711489St.nateldemoura@f5.com     },
11721489St.nateldemoura@f5.com     {
11731489St.nateldemoura@f5.com         nxt_string("dst"),
11741489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
11751489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, dst),
11761489St.nateldemoura@f5.com     },
11771489St.nateldemoura@f5.com     {
11781673St.nateldemoura@f5.com         nxt_string("name"),
11791489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
11801673St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, name),
11811673St.nateldemoura@f5.com     },
11821673St.nateldemoura@f5.com     {
11831673St.nateldemoura@f5.com         nxt_string("type"),
11841673St.nateldemoura@f5.com         NXT_CONF_MAP_INT,
11851673St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, type),
11861489St.nateldemoura@f5.com     },
11871489St.nateldemoura@f5.com     {
11881489St.nateldemoura@f5.com         nxt_string("flags"),
11891489St.nateldemoura@f5.com         NXT_CONF_MAP_INT,
11901489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, flags),
11911489St.nateldemoura@f5.com     },
11921489St.nateldemoura@f5.com     {
11931489St.nateldemoura@f5.com         nxt_string("data"),
11941489St.nateldemoura@f5.com         NXT_CONF_MAP_CSTRZ,
11951489St.nateldemoura@f5.com         offsetof(nxt_fs_mount_t, data),
11961489St.nateldemoura@f5.com     },
11971489St.nateldemoura@f5.com };
11981489St.nateldemoura@f5.com 
11991489St.nateldemoura@f5.com 
1200240Sigor@sysoev.ru static void
1201240Sigor@sysoev.ru nxt_main_port_modules_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1202240Sigor@sysoev.ru {
12031489St.nateldemoura@f5.com     uint32_t               index, jindex, nmounts;
1204240Sigor@sysoev.ru     nxt_mp_t               *mp;
1205240Sigor@sysoev.ru     nxt_int_t              ret;
1206240Sigor@sysoev.ru     nxt_buf_t              *b;
1207549Svbart@nginx.com     nxt_port_t             *port;
1208240Sigor@sysoev.ru     nxt_runtime_t          *rt;
12091489St.nateldemoura@f5.com     nxt_fs_mount_t         *mnt;
12101489St.nateldemoura@f5.com     nxt_conf_value_t       *conf, *root, *value, *mounts;
1211240Sigor@sysoev.ru     nxt_app_lang_module_t  *lang;
1212240Sigor@sysoev.ru 
12131182St.nateldemoura@f5.com     static nxt_str_t root_path = nxt_string("/");
12141489St.nateldemoura@f5.com     static nxt_str_t mounts_name = nxt_string("mounts");
1215240Sigor@sysoev.ru 
1216240Sigor@sysoev.ru     rt = task->thread->runtime;
1217240Sigor@sysoev.ru 
1218240Sigor@sysoev.ru     if (msg->port_msg.pid != rt->port_by_type[NXT_PROCESS_DISCOVERY]->pid) {
1219240Sigor@sysoev.ru         return;
1220240Sigor@sysoev.ru     }
1221240Sigor@sysoev.ru 
12221211Smax.romanov@nginx.com     if (nxt_exiting) {
12231211Smax.romanov@nginx.com         nxt_debug(task, "ignoring discovered modules, exiting");
12241211Smax.romanov@nginx.com         return;
12251211Smax.romanov@nginx.com     }
12261211Smax.romanov@nginx.com 
1227549Svbart@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1228549Svbart@nginx.com                                  msg->port_msg.reply_port);
1229549Svbart@nginx.com 
1230549Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
1231549Svbart@nginx.com         (void) nxt_port_socket_write(task, port, NXT_PORT_MSG_RPC_ERROR, -1,
1232549Svbart@nginx.com                                      msg->port_msg.stream, 0, NULL);
1233549Svbart@nginx.com     }
1234549Svbart@nginx.com 
1235240Sigor@sysoev.ru     b = msg->buf;
1236240Sigor@sysoev.ru 
1237240Sigor@sysoev.ru     if (b == NULL) {
1238240Sigor@sysoev.ru         return;
1239240Sigor@sysoev.ru     }
1240240Sigor@sysoev.ru 
1241240Sigor@sysoev.ru     mp = nxt_mp_create(1024, 128, 256, 32);
1242240Sigor@sysoev.ru     if (mp == NULL) {
1243240Sigor@sysoev.ru         return;
1244240Sigor@sysoev.ru     }
1245240Sigor@sysoev.ru 
1246352Smax.romanov@nginx.com     b = nxt_buf_chk_make_plain(mp, b, msg->size);
1247352Smax.romanov@nginx.com 
1248352Smax.romanov@nginx.com     if (b == NULL) {
1249352Smax.romanov@nginx.com         return;
1250352Smax.romanov@nginx.com     }
1251352Smax.romanov@nginx.com 
1252352Smax.romanov@nginx.com     nxt_debug(task, "application languages: \"%*s\"",
1253352Smax.romanov@nginx.com               b->mem.free - b->mem.pos, b->mem.pos);
1254352Smax.romanov@nginx.com 
1255240Sigor@sysoev.ru     conf = nxt_conf_json_parse(mp, b->mem.pos, b->mem.free, NULL);
1256240Sigor@sysoev.ru     if (conf == NULL) {
1257240Sigor@sysoev.ru         goto fail;
1258240Sigor@sysoev.ru     }
1259240Sigor@sysoev.ru 
1260240Sigor@sysoev.ru     root = nxt_conf_get_path(conf, &root_path);
1261240Sigor@sysoev.ru     if (root == NULL) {
1262240Sigor@sysoev.ru         goto fail;
1263240Sigor@sysoev.ru     }
1264240Sigor@sysoev.ru 
1265240Sigor@sysoev.ru     for (index = 0; /* void */ ; index++) {
1266240Sigor@sysoev.ru         value = nxt_conf_get_array_element(root, index);
1267240Sigor@sysoev.ru         if (value == NULL) {
1268240Sigor@sysoev.ru             break;
1269240Sigor@sysoev.ru         }
1270240Sigor@sysoev.ru 
12711489St.nateldemoura@f5.com         lang = nxt_array_zero_add(rt->languages);
1272240Sigor@sysoev.ru         if (lang == NULL) {
1273240Sigor@sysoev.ru             goto fail;
1274240Sigor@sysoev.ru         }
1275240Sigor@sysoev.ru 
1276240Sigor@sysoev.ru         lang->module = NULL;
1277240Sigor@sysoev.ru 
1278240Sigor@sysoev.ru         ret = nxt_conf_map_object(rt->mem_pool, value, nxt_app_lang_module_map,
1279240Sigor@sysoev.ru                                   nxt_nitems(nxt_app_lang_module_map), lang);
1280240Sigor@sysoev.ru 
1281240Sigor@sysoev.ru         if (ret != NXT_OK) {
1282240Sigor@sysoev.ru             goto fail;
1283240Sigor@sysoev.ru         }
1284240Sigor@sysoev.ru 
12851489St.nateldemoura@f5.com         mounts = nxt_conf_get_object_member(value, &mounts_name, NULL);
12861489St.nateldemoura@f5.com         if (mounts == NULL) {
12871489St.nateldemoura@f5.com             nxt_alert(task, "missing mounts from discovery message.");
12881489St.nateldemoura@f5.com             goto fail;
12891489St.nateldemoura@f5.com         }
12901489St.nateldemoura@f5.com 
12911489St.nateldemoura@f5.com         if (nxt_conf_type(mounts) != NXT_CONF_ARRAY) {
12921489St.nateldemoura@f5.com             nxt_alert(task, "invalid mounts type from discovery message.");
12931489St.nateldemoura@f5.com             goto fail;
12941489St.nateldemoura@f5.com         }
12951489St.nateldemoura@f5.com 
12961489St.nateldemoura@f5.com         nmounts = nxt_conf_array_elements_count(mounts);
12971489St.nateldemoura@f5.com 
12981489St.nateldemoura@f5.com         lang->mounts = nxt_array_create(rt->mem_pool, nmounts,
12991489St.nateldemoura@f5.com                                         sizeof(nxt_fs_mount_t));
13001489St.nateldemoura@f5.com 
13011489St.nateldemoura@f5.com         if (lang->mounts == NULL) {
13021489St.nateldemoura@f5.com             goto fail;
13031489St.nateldemoura@f5.com         }
13041489St.nateldemoura@f5.com 
13051489St.nateldemoura@f5.com         for (jindex = 0; /* */; jindex++) {
13061489St.nateldemoura@f5.com             value = nxt_conf_get_array_element(mounts, jindex);
13071489St.nateldemoura@f5.com             if (value == NULL) {
13081489St.nateldemoura@f5.com                 break;
13091489St.nateldemoura@f5.com             }
13101489St.nateldemoura@f5.com 
13111489St.nateldemoura@f5.com             mnt = nxt_array_zero_add(lang->mounts);
13121489St.nateldemoura@f5.com             if (mnt == NULL) {
13131489St.nateldemoura@f5.com                 goto fail;
13141489St.nateldemoura@f5.com             }
13151489St.nateldemoura@f5.com 
13161585St.nateldemoura@f5.com             mnt->builtin = 1;
13171673St.nateldemoura@f5.com             mnt->deps = 1;
13181585St.nateldemoura@f5.com 
13191489St.nateldemoura@f5.com             ret = nxt_conf_map_object(rt->mem_pool, value,
13201489St.nateldemoura@f5.com                                       nxt_app_lang_mounts_map,
13211489St.nateldemoura@f5.com                                       nxt_nitems(nxt_app_lang_mounts_map), mnt);
13221489St.nateldemoura@f5.com 
13231489St.nateldemoura@f5.com             if (ret != NXT_OK) {
13241489St.nateldemoura@f5.com                 goto fail;
13251489St.nateldemoura@f5.com             }
13261489St.nateldemoura@f5.com         }
13271489St.nateldemoura@f5.com 
13281489St.nateldemoura@f5.com         nxt_debug(task, "lang %d %s \"%s\" (%d mounts)",
13291489St.nateldemoura@f5.com                   lang->type, lang->version, lang->file, lang->mounts->nelts);
1330240Sigor@sysoev.ru     }
1331240Sigor@sysoev.ru 
1332240Sigor@sysoev.ru     qsort(rt->languages->elts, rt->languages->nelts,
1333240Sigor@sysoev.ru           sizeof(nxt_app_lang_module_t), nxt_app_lang_compare);
1334240Sigor@sysoev.ru 
1335240Sigor@sysoev.ru fail:
1336240Sigor@sysoev.ru 
1337240Sigor@sysoev.ru     nxt_mp_destroy(mp);
1338240Sigor@sysoev.ru 
13391488St.nateldemoura@f5.com     ret = nxt_main_process_create(task, nxt_controller_process);
13401488St.nateldemoura@f5.com     if (ret == NXT_OK) {
13411488St.nateldemoura@f5.com         ret = nxt_main_process_create(task, nxt_router_process);
13421488St.nateldemoura@f5.com     }
1343240Sigor@sysoev.ru 
13441488St.nateldemoura@f5.com     if (nxt_slow_path(ret == NXT_ERROR)) {
13451488St.nateldemoura@f5.com         nxt_exiting = 1;
13461488St.nateldemoura@f5.com 
13471488St.nateldemoura@f5.com         nxt_runtime_quit(task, 1);
1348240Sigor@sysoev.ru     }
1349240Sigor@sysoev.ru }
1350240Sigor@sysoev.ru 
1351240Sigor@sysoev.ru 
1352240Sigor@sysoev.ru static int nxt_cdecl
1353240Sigor@sysoev.ru nxt_app_lang_compare(const void *v1, const void *v2)
1354240Sigor@sysoev.ru {
1355240Sigor@sysoev.ru     int                          n;
1356240Sigor@sysoev.ru     const nxt_app_lang_module_t  *lang1, *lang2;
1357240Sigor@sysoev.ru 
1358240Sigor@sysoev.ru     lang1 = v1;
1359240Sigor@sysoev.ru     lang2 = v2;
1360240Sigor@sysoev.ru 
1361356Svbart@nginx.com     n = lang1->type - lang2->type;
1362258Sigor@sysoev.ru 
1363258Sigor@sysoev.ru     if (n != 0) {
1364258Sigor@sysoev.ru         return n;
1365258Sigor@sysoev.ru     }
1366258Sigor@sysoev.ru 
1367354Svbart@nginx.com     n = nxt_strverscmp(lang1->version, lang2->version);
1368240Sigor@sysoev.ru 
1369240Sigor@sysoev.ru     /* Negate result to move higher versions to the beginning. */
1370240Sigor@sysoev.ru 
1371240Sigor@sysoev.ru     return -n;
1372240Sigor@sysoev.ru }
1373314Svbart@nginx.com 
1374314Svbart@nginx.com 
1375314Svbart@nginx.com static void
1376314Svbart@nginx.com nxt_main_port_conf_store_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1377314Svbart@nginx.com {
1378352Smax.romanov@nginx.com     ssize_t        n, size, offset;
1379314Svbart@nginx.com     nxt_buf_t      *b;
1380314Svbart@nginx.com     nxt_int_t      ret;
1381314Svbart@nginx.com     nxt_file_t     file;
1382314Svbart@nginx.com     nxt_runtime_t  *rt;
1383314Svbart@nginx.com 
1384314Svbart@nginx.com     nxt_memzero(&file, sizeof(nxt_file_t));
1385314Svbart@nginx.com 
1386314Svbart@nginx.com     rt = task->thread->runtime;
1387314Svbart@nginx.com 
1388314Svbart@nginx.com     file.name = (nxt_file_name_t *) rt->conf_tmp;
1389314Svbart@nginx.com 
1390314Svbart@nginx.com     if (nxt_slow_path(nxt_file_open(task, &file, NXT_FILE_WRONLY,
1391314Svbart@nginx.com                                     NXT_FILE_TRUNCATE, NXT_FILE_OWNER_ACCESS)
1392314Svbart@nginx.com                       != NXT_OK))
1393314Svbart@nginx.com     {
1394314Svbart@nginx.com         goto error;
1395314Svbart@nginx.com     }
1396314Svbart@nginx.com 
1397352Smax.romanov@nginx.com     offset = 0;
1398352Smax.romanov@nginx.com 
1399314Svbart@nginx.com     for (b = msg->buf; b != NULL; b = b->next) {
1400314Svbart@nginx.com         size = nxt_buf_mem_used_size(&b->mem);
1401314Svbart@nginx.com 
1402352Smax.romanov@nginx.com         n = nxt_file_write(&file, b->mem.pos, size, offset);
1403314Svbart@nginx.com 
1404314Svbart@nginx.com         if (nxt_slow_path(n != size)) {
1405314Svbart@nginx.com             nxt_file_close(task, &file);
1406314Svbart@nginx.com             (void) nxt_file_delete(file.name);
1407314Svbart@nginx.com             goto error;
1408314Svbart@nginx.com         }
1409352Smax.romanov@nginx.com 
1410352Smax.romanov@nginx.com         offset += n;
1411314Svbart@nginx.com     }
1412314Svbart@nginx.com 
1413314Svbart@nginx.com     nxt_file_close(task, &file);
1414314Svbart@nginx.com 
1415314Svbart@nginx.com     ret = nxt_file_rename(file.name, (nxt_file_name_t *) rt->conf);
1416314Svbart@nginx.com 
1417314Svbart@nginx.com     if (nxt_fast_path(ret == NXT_OK)) {
1418314Svbart@nginx.com         return;
1419314Svbart@nginx.com     }
1420314Svbart@nginx.com 
1421314Svbart@nginx.com error:
1422314Svbart@nginx.com 
1423564Svbart@nginx.com     nxt_alert(task, "failed to store current configuration");
1424314Svbart@nginx.com }
1425630Svbart@nginx.com 
1426630Svbart@nginx.com 
1427630Svbart@nginx.com static void
1428630Svbart@nginx.com nxt_main_port_access_log_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
1429630Svbart@nginx.com {
1430630Svbart@nginx.com     u_char               *path;
1431630Svbart@nginx.com     nxt_int_t            ret;
1432630Svbart@nginx.com     nxt_file_t           file;
1433630Svbart@nginx.com     nxt_port_t           *port;
1434630Svbart@nginx.com     nxt_port_msg_type_t  type;
1435630Svbart@nginx.com 
1436630Svbart@nginx.com     nxt_debug(task, "opening access log file");
1437630Svbart@nginx.com 
1438630Svbart@nginx.com     path = msg->buf->mem.pos;
1439630Svbart@nginx.com 
1440630Svbart@nginx.com     nxt_memzero(&file, sizeof(nxt_file_t));
1441630Svbart@nginx.com 
1442630Svbart@nginx.com     file.name = (nxt_file_name_t *) path;
1443630Svbart@nginx.com     file.log_level = NXT_LOG_ERR;
1444630Svbart@nginx.com 
1445630Svbart@nginx.com     ret = nxt_file_open(task, &file, O_WRONLY | O_APPEND, O_CREAT,
1446630Svbart@nginx.com                         NXT_FILE_OWNER_ACCESS);
1447630Svbart@nginx.com 
1448630Svbart@nginx.com     type = (ret == NXT_OK) ? NXT_PORT_MSG_RPC_READY_LAST | NXT_PORT_MSG_CLOSE_FD
1449630Svbart@nginx.com                            : NXT_PORT_MSG_RPC_ERROR;
1450630Svbart@nginx.com 
1451630Svbart@nginx.com     port = nxt_runtime_port_find(task->thread->runtime, msg->port_msg.pid,
1452630Svbart@nginx.com                                  msg->port_msg.reply_port);
1453630Svbart@nginx.com 
1454630Svbart@nginx.com     if (nxt_fast_path(port != NULL)) {
1455630Svbart@nginx.com         (void) nxt_port_socket_write(task, port, type, file.fd,
1456630Svbart@nginx.com                                      msg->port_msg.stream, 0, NULL);
1457630Svbart@nginx.com     }
1458630Svbart@nginx.com }
1459