xref: /unit/src/nxt_router.c (revision 1549)
120Sigor@sysoev.ru 
220Sigor@sysoev.ru /*
320Sigor@sysoev.ru  * Copyright (C) Igor Sysoev
420Sigor@sysoev.ru  * Copyright (C) Valentin V. Bartenev
520Sigor@sysoev.ru  * Copyright (C) NGINX, Inc.
620Sigor@sysoev.ru  */
720Sigor@sysoev.ru 
853Sigor@sysoev.ru #include <nxt_router.h>
9115Sigor@sysoev.ru #include <nxt_conf.h>
10774Svbart@nginx.com #if (NXT_TLS)
11774Svbart@nginx.com #include <nxt_cert.h>
12774Svbart@nginx.com #endif
13431Sigor@sysoev.ru #include <nxt_http.h>
14743Smax.romanov@nginx.com #include <nxt_port_memory_int.h>
15743Smax.romanov@nginx.com #include <nxt_unit_request.h>
16743Smax.romanov@nginx.com #include <nxt_unit_response.h>
171131Smax.romanov@nginx.com #include <nxt_router_request.h>
1820Sigor@sysoev.ru 
19115Sigor@sysoev.ru typedef struct {
20318Smax.romanov@nginx.com     nxt_str_t         type;
21507Smax.romanov@nginx.com     uint32_t          processes;
22507Smax.romanov@nginx.com     uint32_t          max_processes;
23507Smax.romanov@nginx.com     uint32_t          spare_processes;
24318Smax.romanov@nginx.com     nxt_msec_t        timeout;
25427Smax.romanov@nginx.com     nxt_msec_t        res_timeout;
26507Smax.romanov@nginx.com     nxt_msec_t        idle_timeout;
27318Smax.romanov@nginx.com     uint32_t          requests;
28318Smax.romanov@nginx.com     nxt_conf_value_t  *limits_value;
29507Smax.romanov@nginx.com     nxt_conf_value_t  *processes_value;
301473Svbart@nginx.com     nxt_conf_value_t  *targets_value;
31133Sigor@sysoev.ru } nxt_router_app_conf_t;
32133Sigor@sysoev.ru 
33133Sigor@sysoev.ru 
34133Sigor@sysoev.ru typedef struct {
35964Sigor@sysoev.ru     nxt_str_t         pass;
36964Sigor@sysoev.ru     nxt_str_t         application;
37115Sigor@sysoev.ru } nxt_router_listener_conf_t;
38115Sigor@sysoev.ru 
39115Sigor@sysoev.ru 
40774Svbart@nginx.com #if (NXT_TLS)
41774Svbart@nginx.com 
42774Svbart@nginx.com typedef struct {
43774Svbart@nginx.com     nxt_str_t          name;
44774Svbart@nginx.com     nxt_socket_conf_t  *conf;
45774Svbart@nginx.com 
46774Svbart@nginx.com     nxt_queue_link_t   link;  /* for nxt_socket_conf_t.tls */
47774Svbart@nginx.com } nxt_router_tlssock_t;
48774Svbart@nginx.com 
49774Svbart@nginx.com #endif
50774Svbart@nginx.com 
51774Svbart@nginx.com 
52198Sigor@sysoev.ru typedef struct {
53198Sigor@sysoev.ru     nxt_socket_conf_t       *socket_conf;
54198Sigor@sysoev.ru     nxt_router_temp_conf_t  *temp_conf;
55198Sigor@sysoev.ru } nxt_socket_rpc_t;
56198Sigor@sysoev.ru 
57198Sigor@sysoev.ru 
58507Smax.romanov@nginx.com typedef struct {
59507Smax.romanov@nginx.com     nxt_app_t               *app;
60507Smax.romanov@nginx.com     nxt_router_temp_conf_t  *temp_conf;
61507Smax.romanov@nginx.com } nxt_app_rpc_t;
62507Smax.romanov@nginx.com 
63507Smax.romanov@nginx.com 
641488St.nateldemoura@f5.com static nxt_int_t nxt_router_prefork(nxt_task_t *task, nxt_process_t *process,
651488St.nateldemoura@f5.com     nxt_mp_t *mp);
661488St.nateldemoura@f5.com static nxt_int_t nxt_router_start(nxt_task_t *task, nxt_process_data_t *data);
67662Smax.romanov@nginx.com static void nxt_router_greet_controller(nxt_task_t *task,
68662Smax.romanov@nginx.com     nxt_port_t *controller_port);
69662Smax.romanov@nginx.com 
70507Smax.romanov@nginx.com static nxt_int_t nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app);
71425Smax.romanov@nginx.com 
72139Sigor@sysoev.ru static nxt_router_temp_conf_t *nxt_router_temp_conf(nxt_task_t *task);
73198Sigor@sysoev.ru static void nxt_router_conf_apply(nxt_task_t *task, void *obj, void *data);
74198Sigor@sysoev.ru static void nxt_router_conf_ready(nxt_task_t *task,
75139Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
76139Sigor@sysoev.ru static void nxt_router_conf_error(nxt_task_t *task,
77139Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
78139Sigor@sysoev.ru static void nxt_router_conf_send(nxt_task_t *task,
79193Smax.romanov@nginx.com     nxt_router_temp_conf_t *tmcf, nxt_port_msg_type_t type);
8053Sigor@sysoev.ru 
81115Sigor@sysoev.ru static nxt_int_t nxt_router_conf_create(nxt_task_t *task,
82115Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, u_char *start, u_char *end);
831183Svbart@nginx.com static nxt_int_t nxt_router_conf_process_static(nxt_task_t *task,
841183Svbart@nginx.com     nxt_router_conf_t *rtcf, nxt_conf_value_t *conf);
85133Sigor@sysoev.ru static nxt_app_t *nxt_router_app_find(nxt_queue_t *queue, nxt_str_t *name);
86198Sigor@sysoev.ru static void nxt_router_listen_socket_rpc_create(nxt_task_t *task,
87198Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, nxt_socket_conf_t *skcf);
88198Sigor@sysoev.ru static void nxt_router_listen_socket_ready(nxt_task_t *task,
89198Sigor@sysoev.ru     nxt_port_recv_msg_t *msg, void *data);
90198Sigor@sysoev.ru static void nxt_router_listen_socket_error(nxt_task_t *task,
91198Sigor@sysoev.ru     nxt_port_recv_msg_t *msg, void *data);
92774Svbart@nginx.com #if (NXT_TLS)
93774Svbart@nginx.com static void nxt_router_tls_rpc_create(nxt_task_t *task,
94774Svbart@nginx.com     nxt_router_temp_conf_t *tmcf, nxt_router_tlssock_t *tls);
95774Svbart@nginx.com static void nxt_router_tls_rpc_handler(nxt_task_t *task,
96774Svbart@nginx.com     nxt_port_recv_msg_t *msg, void *data);
97774Svbart@nginx.com #endif
98507Smax.romanov@nginx.com static void nxt_router_app_rpc_create(nxt_task_t *task,
99507Smax.romanov@nginx.com     nxt_router_temp_conf_t *tmcf, nxt_app_t *app);
100507Smax.romanov@nginx.com static void nxt_router_app_prefork_ready(nxt_task_t *task,
101507Smax.romanov@nginx.com     nxt_port_recv_msg_t *msg, void *data);
102507Smax.romanov@nginx.com static void nxt_router_app_prefork_error(nxt_task_t *task,
103507Smax.romanov@nginx.com     nxt_port_recv_msg_t *msg, void *data);
104359Sigor@sysoev.ru static nxt_socket_conf_t *nxt_router_socket_conf(nxt_task_t *task,
105359Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf, nxt_str_t *name);
106359Sigor@sysoev.ru static nxt_int_t nxt_router_listen_socket_find(nxt_router_temp_conf_t *tmcf,
107359Sigor@sysoev.ru     nxt_socket_conf_t *nskcf, nxt_sockaddr_t *sa);
10853Sigor@sysoev.ru 
10953Sigor@sysoev.ru static nxt_int_t nxt_router_engines_create(nxt_task_t *task,
11053Sigor@sysoev.ru     nxt_router_t *router, nxt_router_temp_conf_t *tmcf,
11153Sigor@sysoev.ru     const nxt_event_interface_t *interface);
112115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_create(nxt_router_temp_conf_t *tmcf,
113115Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
114115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_update(nxt_router_temp_conf_t *tmcf,
115115Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
116115Sigor@sysoev.ru static nxt_int_t nxt_router_engine_conf_delete(nxt_router_temp_conf_t *tmcf,
117115Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
118154Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_create(nxt_router_temp_conf_t *tmcf,
119154Sigor@sysoev.ru     nxt_router_engine_conf_t *recf, nxt_queue_t *sockets,
120154Sigor@sysoev.ru     nxt_work_handler_t handler);
121313Sigor@sysoev.ru static nxt_int_t nxt_router_engine_quit(nxt_router_temp_conf_t *tmcf,
122313Sigor@sysoev.ru     nxt_router_engine_conf_t *recf);
123139Sigor@sysoev.ru static nxt_int_t nxt_router_engine_joints_delete(nxt_router_temp_conf_t *tmcf,
124139Sigor@sysoev.ru     nxt_router_engine_conf_t *recf, nxt_queue_t *sockets);
12553Sigor@sysoev.ru 
12653Sigor@sysoev.ru static nxt_int_t nxt_router_threads_create(nxt_task_t *task, nxt_runtime_t *rt,
12753Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
12853Sigor@sysoev.ru static nxt_int_t nxt_router_thread_create(nxt_task_t *task, nxt_runtime_t *rt,
12953Sigor@sysoev.ru     nxt_event_engine_t *engine);
130343Smax.romanov@nginx.com static void nxt_router_apps_sort(nxt_task_t *task, nxt_router_t *router,
131133Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
13253Sigor@sysoev.ru 
133315Sigor@sysoev.ru static void nxt_router_engines_post(nxt_router_t *router,
134315Sigor@sysoev.ru     nxt_router_temp_conf_t *tmcf);
135315Sigor@sysoev.ru static void nxt_router_engine_post(nxt_event_engine_t *engine,
136315Sigor@sysoev.ru     nxt_work_t *jobs);
13753Sigor@sysoev.ru 
13853Sigor@sysoev.ru static void nxt_router_thread_start(void *data);
1391545Smax.romanov@nginx.com static void nxt_router_rt_add_port(nxt_task_t *task, void *obj,
1401545Smax.romanov@nginx.com     void *data);
14153Sigor@sysoev.ru static void nxt_router_listen_socket_create(nxt_task_t *task, void *obj,
14253Sigor@sysoev.ru     void *data);
14353Sigor@sysoev.ru static void nxt_router_listen_socket_update(nxt_task_t *task, void *obj,
14453Sigor@sysoev.ru     void *data);
14553Sigor@sysoev.ru static void nxt_router_listen_socket_delete(nxt_task_t *task, void *obj,
14653Sigor@sysoev.ru     void *data);
147313Sigor@sysoev.ru static void nxt_router_worker_thread_quit(nxt_task_t *task, void *obj,
148313Sigor@sysoev.ru     void *data);
14953Sigor@sysoev.ru static void nxt_router_listen_socket_close(nxt_task_t *task, void *obj,
15053Sigor@sysoev.ru     void *data);
15153Sigor@sysoev.ru static void nxt_router_thread_exit_handler(nxt_task_t *task, void *obj,
15253Sigor@sysoev.ru     void *data);
1531547Smax.romanov@nginx.com static void nxt_router_req_headers_ack_handler(nxt_task_t *task,
1541547Smax.romanov@nginx.com     nxt_port_recv_msg_t *msg, nxt_request_rpc_data_t *req_rpc_data);
155359Sigor@sysoev.ru static void nxt_router_listen_socket_release(nxt_task_t *task,
156359Sigor@sysoev.ru     nxt_socket_conf_t *skcf);
15753Sigor@sysoev.ru 
158630Svbart@nginx.com static void nxt_router_access_log_writer(nxt_task_t *task,
159630Svbart@nginx.com     nxt_http_request_t *r, nxt_router_access_log_t *access_log);
160630Svbart@nginx.com static u_char *nxt_router_access_log_date(u_char *buf, nxt_realtime_t *now,
161630Svbart@nginx.com     struct tm *tm, size_t size, const char *format);
162630Svbart@nginx.com static void nxt_router_access_log_open(nxt_task_t *task,
163630Svbart@nginx.com     nxt_router_temp_conf_t *tmcf);
164630Svbart@nginx.com static void nxt_router_access_log_ready(nxt_task_t *task,
165630Svbart@nginx.com     nxt_port_recv_msg_t *msg, void *data);
166630Svbart@nginx.com static void nxt_router_access_log_error(nxt_task_t *task,
167630Svbart@nginx.com     nxt_port_recv_msg_t *msg, void *data);
168630Svbart@nginx.com static void nxt_router_access_log_release(nxt_task_t *task,
169630Svbart@nginx.com     nxt_thread_spinlock_t *lock, nxt_router_access_log_t *access_log);
170651Svbart@nginx.com static void nxt_router_access_log_reopen_completion(nxt_task_t *task, void *obj,
171651Svbart@nginx.com     void *data);
172631Svbart@nginx.com static void nxt_router_access_log_reopen_ready(nxt_task_t *task,
173631Svbart@nginx.com     nxt_port_recv_msg_t *msg, void *data);
174631Svbart@nginx.com static void nxt_router_access_log_reopen_error(nxt_task_t *task,
175631Svbart@nginx.com     nxt_port_recv_msg_t *msg, void *data);
176630Svbart@nginx.com 
177343Smax.romanov@nginx.com static void nxt_router_app_port_ready(nxt_task_t *task,
178343Smax.romanov@nginx.com     nxt_port_recv_msg_t *msg, void *data);
1791547Smax.romanov@nginx.com static nxt_int_t nxt_router_app_shared_port_send(nxt_task_t *task,
1801547Smax.romanov@nginx.com     nxt_port_t *app_port);
181343Smax.romanov@nginx.com static void nxt_router_app_port_error(nxt_task_t *task,
182343Smax.romanov@nginx.com     nxt_port_recv_msg_t *msg, void *data);
183343Smax.romanov@nginx.com 
184753Smax.romanov@nginx.com static void nxt_router_app_unlink(nxt_task_t *task, nxt_app_t *app);
1851123Smax.romanov@nginx.com 
186343Smax.romanov@nginx.com static void nxt_router_app_port_release(nxt_task_t *task, nxt_port_t *port,
1871123Smax.romanov@nginx.com     nxt_apr_action_t action);
1881547Smax.romanov@nginx.com static void nxt_router_app_port_get(nxt_task_t *task, nxt_app_t *app,
1891547Smax.romanov@nginx.com     nxt_request_rpc_data_t *req_rpc_data);
1901547Smax.romanov@nginx.com static void nxt_router_http_request_done(nxt_task_t *task, void *obj,
1911547Smax.romanov@nginx.com     void *data);
192141Smax.romanov@nginx.com 
193425Smax.romanov@nginx.com static void nxt_router_app_prepare_request(nxt_task_t *task,
1941547Smax.romanov@nginx.com     nxt_request_rpc_data_t *req_rpc_data);
1951007Salexander.borisov@nginx.com static nxt_buf_t *nxt_router_prepare_msg(nxt_task_t *task,
1961547Smax.romanov@nginx.com     nxt_http_request_t *r, nxt_app_t *app, const nxt_str_t *prefix);
197510Salexander.borisov@nginx.com 
198318Smax.romanov@nginx.com static void nxt_router_app_timeout(nxt_task_t *task, void *obj, void *data);
199507Smax.romanov@nginx.com static void nxt_router_adjust_idle_timer(nxt_task_t *task, void *obj,
200507Smax.romanov@nginx.com     void *data);
201507Smax.romanov@nginx.com static void nxt_router_app_idle_timeout(nxt_task_t *task, void *obj,
202507Smax.romanov@nginx.com     void *data);
203753Smax.romanov@nginx.com static void nxt_router_app_joint_release_handler(nxt_task_t *task, void *obj,
204507Smax.romanov@nginx.com     void *data);
205753Smax.romanov@nginx.com static void nxt_router_free_app(nxt_task_t *task, void *obj, void *data);
206431Sigor@sysoev.ru 
207431Sigor@sysoev.ru static const nxt_http_request_state_t  nxt_http_request_send_state;
208431Sigor@sysoev.ru static void nxt_http_request_send_body(nxt_task_t *task, void *obj, void *data);
209141Smax.romanov@nginx.com 
210753Smax.romanov@nginx.com static void nxt_router_app_joint_use(nxt_task_t *task,
211753Smax.romanov@nginx.com     nxt_app_joint_t *app_joint, int i);
212753Smax.romanov@nginx.com 
2131547Smax.romanov@nginx.com static void nxt_router_http_request_release_post(nxt_task_t *task,
2141007Salexander.borisov@nginx.com     nxt_http_request_t *r);
2151007Salexander.borisov@nginx.com static void nxt_router_http_request_release(nxt_task_t *task, void *obj,
2161007Salexander.borisov@nginx.com     void *data);
2171321Smax.romanov@nginx.com static void nxt_router_oosm_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg);
2181545Smax.romanov@nginx.com static void nxt_router_get_port_handler(nxt_task_t *task,
2191545Smax.romanov@nginx.com     nxt_port_recv_msg_t *msg);
2201546Smax.romanov@nginx.com static void nxt_router_get_mmap_handler(nxt_task_t *task,
2211546Smax.romanov@nginx.com     nxt_port_recv_msg_t *msg);
2221007Salexander.borisov@nginx.com 
2231149Smax.romanov@nginx.com extern const nxt_http_request_state_t  nxt_http_websocket;
2241131Smax.romanov@nginx.com 
225119Smax.romanov@nginx.com static nxt_router_t  *nxt_router;
22620Sigor@sysoev.ru 
227743Smax.romanov@nginx.com static const nxt_str_t http_prefix = nxt_string("HTTP_");
228743Smax.romanov@nginx.com static const nxt_str_t empty_prefix = nxt_string("");
229743Smax.romanov@nginx.com 
230743Smax.romanov@nginx.com static const nxt_str_t  *nxt_app_msg_prefix[] = {
231804Svbart@nginx.com     &empty_prefix,
232743Smax.romanov@nginx.com     &http_prefix,
233743Smax.romanov@nginx.com     &http_prefix,
234743Smax.romanov@nginx.com     &http_prefix,
235743Smax.romanov@nginx.com     &http_prefix,
236977Smax.romanov@gmail.com     &empty_prefix,
237216Sigor@sysoev.ru };
238216Sigor@sysoev.ru 
239216Sigor@sysoev.ru 
2401488St.nateldemoura@f5.com static const nxt_port_handlers_t  nxt_router_process_port_handlers = {
2411488St.nateldemoura@f5.com     .quit         = nxt_signal_quit_handler,
242662Smax.romanov@nginx.com     .new_port     = nxt_router_new_port_handler,
2431545Smax.romanov@nginx.com     .get_port     = nxt_router_get_port_handler,
244662Smax.romanov@nginx.com     .change_file  = nxt_port_change_log_file_handler,
245662Smax.romanov@nginx.com     .mmap         = nxt_port_mmap_handler,
2461546Smax.romanov@nginx.com     .get_mmap     = nxt_router_get_mmap_handler,
247662Smax.romanov@nginx.com     .data         = nxt_router_conf_data_handler,
248662Smax.romanov@nginx.com     .remove_pid   = nxt_router_remove_pid_handler,
249662Smax.romanov@nginx.com     .access_log   = nxt_router_access_log_reopen_handler,
250662Smax.romanov@nginx.com     .rpc_ready    = nxt_port_rpc_handler,
251662Smax.romanov@nginx.com     .rpc_error    = nxt_port_rpc_handler,
2521321Smax.romanov@nginx.com     .oosm         = nxt_router_oosm_handler,
253662Smax.romanov@nginx.com };
254662Smax.romanov@nginx.com 
255662Smax.romanov@nginx.com 
2561488St.nateldemoura@f5.com const nxt_process_init_t  nxt_router_process = {
2571488St.nateldemoura@f5.com     .name           = "router",
2581488St.nateldemoura@f5.com     .type           = NXT_PROCESS_ROUTER,
2591488St.nateldemoura@f5.com     .prefork        = nxt_router_prefork,
2601488St.nateldemoura@f5.com     .restart        = 1,
2611488St.nateldemoura@f5.com     .setup          = nxt_process_core_setup,
2621488St.nateldemoura@f5.com     .start          = nxt_router_start,
2631488St.nateldemoura@f5.com     .port_handlers  = &nxt_router_process_port_handlers,
2641488St.nateldemoura@f5.com     .signals        = nxt_process_signals,
2651488St.nateldemoura@f5.com };
2661488St.nateldemoura@f5.com 
2671488St.nateldemoura@f5.com 
2681509Sigor@sysoev.ru /* Queues of nxt_socket_conf_t */
2691509Sigor@sysoev.ru nxt_queue_t  creating_sockets;
2701509Sigor@sysoev.ru nxt_queue_t  pending_sockets;
2711509Sigor@sysoev.ru nxt_queue_t  updating_sockets;
2721509Sigor@sysoev.ru nxt_queue_t  keeping_sockets;
2731509Sigor@sysoev.ru nxt_queue_t  deleting_sockets;
2741509Sigor@sysoev.ru 
2751509Sigor@sysoev.ru 
2761488St.nateldemoura@f5.com static nxt_int_t
2771488St.nateldemoura@f5.com nxt_router_prefork(nxt_task_t *task, nxt_process_t *process, nxt_mp_t *mp)
2781488St.nateldemoura@f5.com {
2791488St.nateldemoura@f5.com     nxt_runtime_stop_app_processes(task, task->thread->runtime);
2801488St.nateldemoura@f5.com 
2811488St.nateldemoura@f5.com     return NXT_OK;
2821488St.nateldemoura@f5.com }
2831488St.nateldemoura@f5.com 
2841488St.nateldemoura@f5.com 
2851488St.nateldemoura@f5.com static nxt_int_t
2861488St.nateldemoura@f5.com nxt_router_start(nxt_task_t *task, nxt_process_data_t *data)
28720Sigor@sysoev.ru {
288141Smax.romanov@nginx.com     nxt_int_t      ret;
289662Smax.romanov@nginx.com     nxt_port_t     *controller_port;
290141Smax.romanov@nginx.com     nxt_router_t   *router;
291141Smax.romanov@nginx.com     nxt_runtime_t  *rt;
292141Smax.romanov@nginx.com 
293141Smax.romanov@nginx.com     rt = task->thread->runtime;
29453Sigor@sysoev.ru 
2951488St.nateldemoura@f5.com     nxt_log(task, NXT_LOG_INFO, "router started");
2961488St.nateldemoura@f5.com 
297771Sigor@sysoev.ru #if (NXT_TLS)
298771Sigor@sysoev.ru     rt->tls = nxt_service_get(rt->services, "SSL/TLS", "OpenSSL");
299771Sigor@sysoev.ru     if (nxt_slow_path(rt->tls == NULL)) {
300771Sigor@sysoev.ru         return NXT_ERROR;
301771Sigor@sysoev.ru     }
302771Sigor@sysoev.ru 
303771Sigor@sysoev.ru     ret = rt->tls->library_init(task);
304771Sigor@sysoev.ru     if (nxt_slow_path(ret != NXT_OK)) {
305771Sigor@sysoev.ru         return ret;
306771Sigor@sysoev.ru     }
307771Sigor@sysoev.ru #endif
308771Sigor@sysoev.ru 
3091459Smax.romanov@nginx.com     ret = nxt_http_init(task);
31088Smax.romanov@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
31188Smax.romanov@nginx.com         return ret;
31288Smax.romanov@nginx.com     }
31388Smax.romanov@nginx.com 
31453Sigor@sysoev.ru     router = nxt_zalloc(sizeof(nxt_router_t));
31553Sigor@sysoev.ru     if (nxt_slow_path(router == NULL)) {
31653Sigor@sysoev.ru         return NXT_ERROR;
31753Sigor@sysoev.ru     }
31853Sigor@sysoev.ru 
31953Sigor@sysoev.ru     nxt_queue_init(&router->engines);
32053Sigor@sysoev.ru     nxt_queue_init(&router->sockets);
321133Sigor@sysoev.ru     nxt_queue_init(&router->apps);
32253Sigor@sysoev.ru 
323119Smax.romanov@nginx.com     nxt_router = router;
324119Smax.romanov@nginx.com 
325662Smax.romanov@nginx.com     controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER];
326662Smax.romanov@nginx.com     if (controller_port != NULL) {
327662Smax.romanov@nginx.com         nxt_router_greet_controller(task, controller_port);
328662Smax.romanov@nginx.com     }
329662Smax.romanov@nginx.com 
330115Sigor@sysoev.ru     return NXT_OK;
331115Sigor@sysoev.ru }
332115Sigor@sysoev.ru 
333115Sigor@sysoev.ru 
334343Smax.romanov@nginx.com static void
335662Smax.romanov@nginx.com nxt_router_greet_controller(nxt_task_t *task, nxt_port_t *controller_port)
336662Smax.romanov@nginx.com {
337662Smax.romanov@nginx.com     nxt_port_socket_write(task, controller_port, NXT_PORT_MSG_PROCESS_READY,
338662Smax.romanov@nginx.com                           -1, 0, 0, NULL);
339662Smax.romanov@nginx.com }
340662Smax.romanov@nginx.com 
341662Smax.romanov@nginx.com 
342662Smax.romanov@nginx.com static void
343507Smax.romanov@nginx.com nxt_router_start_app_process_handler(nxt_task_t *task, nxt_port_t *port,
344507Smax.romanov@nginx.com     void *data)
345167Smax.romanov@nginx.com {
346343Smax.romanov@nginx.com     size_t         size;
347343Smax.romanov@nginx.com     uint32_t       stream;
348430Sigor@sysoev.ru     nxt_mp_t       *mp;
349648Svbart@nginx.com     nxt_int_t      ret;
350343Smax.romanov@nginx.com     nxt_app_t      *app;
351343Smax.romanov@nginx.com     nxt_buf_t      *b;
352343Smax.romanov@nginx.com     nxt_port_t     *main_port;
353343Smax.romanov@nginx.com     nxt_runtime_t  *rt;
354343Smax.romanov@nginx.com 
355343Smax.romanov@nginx.com     app = data;
356167Smax.romanov@nginx.com 
357167Smax.romanov@nginx.com     rt = task->thread->runtime;
358240Sigor@sysoev.ru     main_port = rt->port_by_type[NXT_PROCESS_MAIN];
359167Smax.romanov@nginx.com 
360507Smax.romanov@nginx.com     nxt_debug(task, "app '%V' %p start process", &app->name, app);
361343Smax.romanov@nginx.com 
362343Smax.romanov@nginx.com     size = app->name.length + 1 + app->conf.length;
363343Smax.romanov@nginx.com 
364343Smax.romanov@nginx.com     b = nxt_buf_mem_ts_alloc(task, task->thread->engine->mem_pool, size);
365343Smax.romanov@nginx.com 
366343Smax.romanov@nginx.com     if (nxt_slow_path(b == NULL)) {
367343Smax.romanov@nginx.com         goto failed;
368167Smax.romanov@nginx.com     }
369167Smax.romanov@nginx.com 
370343Smax.romanov@nginx.com     nxt_buf_cpystr(b, &app->name);
371343Smax.romanov@nginx.com     *b->mem.free++ = '\0';
372343Smax.romanov@nginx.com     nxt_buf_cpystr(b, &app->conf);
373343Smax.romanov@nginx.com 
374753Smax.romanov@nginx.com     nxt_router_app_joint_use(task, app->joint, 1);
375753Smax.romanov@nginx.com 
376343Smax.romanov@nginx.com     stream = nxt_port_rpc_register_handler(task, port,
377343Smax.romanov@nginx.com                                            nxt_router_app_port_ready,
378343Smax.romanov@nginx.com                                            nxt_router_app_port_error,
379753Smax.romanov@nginx.com                                            -1, app->joint);
380343Smax.romanov@nginx.com 
381343Smax.romanov@nginx.com     if (nxt_slow_path(stream == 0)) {
382753Smax.romanov@nginx.com         nxt_router_app_joint_use(task, app->joint, -1);
383753Smax.romanov@nginx.com 
384343Smax.romanov@nginx.com         goto failed;
385343Smax.romanov@nginx.com     }
386343Smax.romanov@nginx.com 
3871488St.nateldemoura@f5.com     ret = nxt_port_socket_write(task, main_port, NXT_PORT_MSG_START_PROCESS,
3881488St.nateldemoura@f5.com                                 -1, stream, port->id, b);
389648Svbart@nginx.com 
390648Svbart@nginx.com     if (nxt_slow_path(ret != NXT_OK)) {
391648Svbart@nginx.com         nxt_port_rpc_cancel(task, port, stream);
392753Smax.romanov@nginx.com 
393753Smax.romanov@nginx.com         nxt_router_app_joint_use(task, app->joint, -1);
394753Smax.romanov@nginx.com 
395648Svbart@nginx.com         goto failed;
396648Svbart@nginx.com     }
397343Smax.romanov@nginx.com 
398753Smax.romanov@nginx.com     nxt_router_app_use(task, app, -1);
399753Smax.romanov@nginx.com 
400343Smax.romanov@nginx.com     return;
401343Smax.romanov@nginx.com 
402343Smax.romanov@nginx.com failed:
403343Smax.romanov@nginx.com 
404648Svbart@nginx.com     if (b != NULL) {
405648Svbart@nginx.com         mp = b->data;
406648Svbart@nginx.com         nxt_mp_free(mp, b);
407648Svbart@nginx.com         nxt_mp_release(mp);
408648Svbart@nginx.com     }
409648Svbart@nginx.com 
410343Smax.romanov@nginx.com     nxt_thread_mutex_lock(&app->mutex);
411343Smax.romanov@nginx.com 
412507Smax.romanov@nginx.com     app->pending_processes--;
413343Smax.romanov@nginx.com 
414343Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&app->mutex);
415343Smax.romanov@nginx.com 
416343Smax.romanov@nginx.com     nxt_router_app_use(task, app, -1);
417167Smax.romanov@nginx.com }
418167Smax.romanov@nginx.com 
419167Smax.romanov@nginx.com 
420753Smax.romanov@nginx.com static void
421753Smax.romanov@nginx.com nxt_router_app_joint_use(nxt_task_t *task, nxt_app_joint_t *app_joint, int i)
422753Smax.romanov@nginx.com {
423753Smax.romanov@nginx.com     app_joint->use_count += i;
424753Smax.romanov@nginx.com 
425753Smax.romanov@nginx.com     if (app_joint->use_count == 0) {
426753Smax.romanov@nginx.com         nxt_assert(app_joint->app == NULL);
427753Smax.romanov@nginx.com 
428753Smax.romanov@nginx.com         nxt_free(app_joint);
429753Smax.romanov@nginx.com     }
430753Smax.romanov@nginx.com }
431753Smax.romanov@nginx.com 
432753Smax.romanov@nginx.com 
433343Smax.romanov@nginx.com static nxt_int_t
434507Smax.romanov@nginx.com nxt_router_start_app_process(nxt_task_t *task, nxt_app_t *app)
435141Smax.romanov@nginx.com {
436343Smax.romanov@nginx.com     nxt_int_t      res;
437343Smax.romanov@nginx.com     nxt_port_t     *router_port;
438343Smax.romanov@nginx.com     nxt_runtime_t  *rt;
439343Smax.romanov@nginx.com 
440*1549Smax.romanov@nginx.com     nxt_debug(task, "app '%V' start process", &app->name);
441*1549Smax.romanov@nginx.com 
442343Smax.romanov@nginx.com     rt = task->thread->runtime;
443343Smax.romanov@nginx.com     router_port = rt->port_by_type[NXT_PROCESS_ROUTER];
444343Smax.romanov@nginx.com 
445343Smax.romanov@nginx.com     nxt_router_app_use(task, app, 1);
446343Smax.romanov@nginx.com 
447507Smax.romanov@nginx.com     res = nxt_port_post(task, router_port, nxt_router_start_app_process_handler,
448343Smax.romanov@nginx.com                         app);
449343Smax.romanov@nginx.com 
450343Smax.romanov@nginx.com     if (res == NXT_OK) {
451343Smax.romanov@nginx.com         return res;
452318Smax.romanov@nginx.com     }
453318Smax.romanov@nginx.com 
454343Smax.romanov@nginx.com     nxt_thread_mutex_lock(&app->mutex);
455343Smax.romanov@nginx.com 
456507Smax.romanov@nginx.com     app->pending_processes--;
457343Smax.romanov@nginx.com 
458343Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&app->mutex);
459343Smax.romanov@nginx.com 
460343Smax.romanov@nginx.com     nxt_router_app_use(task, app, -1);
461343Smax.romanov@nginx.com 
462343Smax.romanov@nginx.com     return NXT_ERROR;
463318Smax.romanov@nginx.com }
464318Smax.romanov@nginx.com 
465318Smax.romanov@nginx.com 
466423Smax.romanov@nginx.com nxt_inline nxt_bool_t
467423Smax.romanov@nginx.com nxt_router_msg_cancel(nxt_task_t *task, nxt_msg_info_t *msg_info,
468423Smax.romanov@nginx.com     uint32_t stream)
469423Smax.romanov@nginx.com {
470423Smax.romanov@nginx.com     nxt_buf_t   *b, *next;
471423Smax.romanov@nginx.com     nxt_bool_t  cancelled;
472423Smax.romanov@nginx.com 
473423Smax.romanov@nginx.com     if (msg_info->buf == NULL) {
474423Smax.romanov@nginx.com         return 0;
475423Smax.romanov@nginx.com     }
476423Smax.romanov@nginx.com 
477423Smax.romanov@nginx.com     cancelled = nxt_port_mmap_tracking_cancel(task, &msg_info->tracking,
478423Smax.romanov@nginx.com                                               stream);
479423Smax.romanov@nginx.com 
480423Smax.romanov@nginx.com     if (cancelled) {
481423Smax.romanov@nginx.com         nxt_debug(task, "stream #%uD: cancelled by router", stream);
482423Smax.romanov@nginx.com     }
483423Smax.romanov@nginx.com 
484423Smax.romanov@nginx.com     for (b = msg_info->buf; b != NULL; b = next) {
485423Smax.romanov@nginx.com         next = b->next;
4861269Sigor@sysoev.ru         b->next = NULL;
487423Smax.romanov@nginx.com 
488423Smax.romanov@nginx.com         b->completion_handler = msg_info->completion_handler;
489423Smax.romanov@nginx.com 
490423Smax.romanov@nginx.com         if (b->is_port_mmap_sent) {
491423Smax.romanov@nginx.com             b->is_port_mmap_sent = cancelled == 0;
492423Smax.romanov@nginx.com             b->completion_handler(task, b, b->parent);
493423Smax.romanov@nginx.com         }
494423Smax.romanov@nginx.com     }
495423Smax.romanov@nginx.com 
496423Smax.romanov@nginx.com     msg_info->buf = NULL;
497423Smax.romanov@nginx.com 
498423Smax.romanov@nginx.com     return cancelled;
499423Smax.romanov@nginx.com }
500423Smax.romanov@nginx.com 
501423Smax.romanov@nginx.com 
502425Smax.romanov@nginx.com nxt_inline nxt_bool_t
503425Smax.romanov@nginx.com nxt_queue_chk_remove(nxt_queue_link_t *lnk)
504425Smax.romanov@nginx.com {
505425Smax.romanov@nginx.com     if (lnk->next != NULL) {
506425Smax.romanov@nginx.com         nxt_queue_remove(lnk);
507425Smax.romanov@nginx.com 
508425Smax.romanov@nginx.com         lnk->next = NULL;
509425Smax.romanov@nginx.com 
510425Smax.romanov@nginx.com         return 1;
511425Smax.romanov@nginx.com     }
512425Smax.romanov@nginx.com 
513425Smax.romanov@nginx.com     return 0;
514425Smax.romanov@nginx.com }
515425Smax.romanov@nginx.com 
516425Smax.romanov@nginx.com 
517343Smax.romanov@nginx.com nxt_inline void
5181123Smax.romanov@nginx.com nxt_request_rpc_data_unlink(nxt_task_t *task,
5191123Smax.romanov@nginx.com     nxt_request_rpc_data_t *req_rpc_data)
520343Smax.romanov@nginx.com {
5211547Smax.romanov@nginx.com     nxt_http_request_t  *r;
5221547Smax.romanov@nginx.com 
5231547Smax.romanov@nginx.com     nxt_router_msg_cancel(task, &req_rpc_data->msg_info, req_rpc_data->stream);
5241123Smax.romanov@nginx.com 
5251123Smax.romanov@nginx.com     if (req_rpc_data->app_port != NULL) {
5261123Smax.romanov@nginx.com         nxt_router_app_port_release(task, req_rpc_data->app_port,
5271123Smax.romanov@nginx.com                                     req_rpc_data->apr_action);
5281123Smax.romanov@nginx.com 
5291123Smax.romanov@nginx.com         req_rpc_data->app_port = NULL;
5301123Smax.romanov@nginx.com     }
5311123Smax.romanov@nginx.com 
5321123Smax.romanov@nginx.com     if (req_rpc_data->app != NULL) {
5331123Smax.romanov@nginx.com         nxt_router_app_use(task, req_rpc_data->app, -1);
5341123Smax.romanov@nginx.com 
5351123Smax.romanov@nginx.com         req_rpc_data->app = NULL;
5361123Smax.romanov@nginx.com     }
5371123Smax.romanov@nginx.com 
5381547Smax.romanov@nginx.com     r = req_rpc_data->request;
5391547Smax.romanov@nginx.com 
5401547Smax.romanov@nginx.com     if (r != NULL) {
5411547Smax.romanov@nginx.com         r->timer_data = NULL;
5421547Smax.romanov@nginx.com 
5431547Smax.romanov@nginx.com         nxt_router_http_request_release_post(task, r);
5441547Smax.romanov@nginx.com 
5451547Smax.romanov@nginx.com         r->req_rpc_data = NULL;
5461123Smax.romanov@nginx.com         req_rpc_data->request = NULL;
547346Smax.romanov@nginx.com     }
5481547Smax.romanov@nginx.com 
5491547Smax.romanov@nginx.com     if (req_rpc_data->msg_info.body_fd != -1) {
5501547Smax.romanov@nginx.com         nxt_fd_close(req_rpc_data->msg_info.body_fd);
5511547Smax.romanov@nginx.com 
5521547Smax.romanov@nginx.com         req_rpc_data->msg_info.body_fd = -1;
5531547Smax.romanov@nginx.com     }
5541547Smax.romanov@nginx.com 
5551547Smax.romanov@nginx.com     if (req_rpc_data->rpc_cancel) {
5561547Smax.romanov@nginx.com         req_rpc_data->rpc_cancel = 0;
5571547Smax.romanov@nginx.com 
5581547Smax.romanov@nginx.com         nxt_port_rpc_cancel(task, task->thread->engine->port,
5591547Smax.romanov@nginx.com                             req_rpc_data->stream);
5601547Smax.romanov@nginx.com     }
561343Smax.romanov@nginx.com }
562343Smax.romanov@nginx.com 
563343Smax.romanov@nginx.com 
564141Smax.romanov@nginx.com void
565141Smax.romanov@nginx.com nxt_router_new_port_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
566141Smax.romanov@nginx.com {
5671547Smax.romanov@nginx.com     nxt_app_t      *app;
5681547Smax.romanov@nginx.com     nxt_port_t     *port, *main_app_port;
5691547Smax.romanov@nginx.com     nxt_runtime_t  *rt;
5701547Smax.romanov@nginx.com 
571141Smax.romanov@nginx.com     nxt_port_new_port_handler(task, msg);
572141Smax.romanov@nginx.com 
5731547Smax.romanov@nginx.com     port = msg->u.new_port;
5741547Smax.romanov@nginx.com 
5751547Smax.romanov@nginx.com     if (port != NULL && port->type == NXT_PROCESS_CONTROLLER) {
576662Smax.romanov@nginx.com         nxt_router_greet_controller(task, msg->u.new_port);
577662Smax.romanov@nginx.com     }
578662Smax.romanov@nginx.com 
5791547Smax.romanov@nginx.com     if (port == NULL || port->type != NXT_PROCESS_APP) {
5801547Smax.romanov@nginx.com 
5811547Smax.romanov@nginx.com         if (msg->port_msg.stream == 0) {
5821547Smax.romanov@nginx.com             return;
5831547Smax.romanov@nginx.com         }
5841547Smax.romanov@nginx.com 
5851547Smax.romanov@nginx.com         msg->port_msg.type = _NXT_PORT_MSG_RPC_ERROR;
5861547Smax.romanov@nginx.com     }
5871547Smax.romanov@nginx.com 
5881547Smax.romanov@nginx.com     if (msg->port_msg.stream != 0) {
5891547Smax.romanov@nginx.com         nxt_port_rpc_handler(task, msg);
590141Smax.romanov@nginx.com         return;
591141Smax.romanov@nginx.com     }
592141Smax.romanov@nginx.com 
5931547Smax.romanov@nginx.com     /*
5941547Smax.romanov@nginx.com      * Port with "id == 0" is application 'main' port and it always
5951547Smax.romanov@nginx.com      * should come with non-zero stream.
5961547Smax.romanov@nginx.com      */
5971547Smax.romanov@nginx.com     nxt_assert(port->id != 0);
5981547Smax.romanov@nginx.com 
5991547Smax.romanov@nginx.com     /* Find 'main' app port and get app reference. */
6001547Smax.romanov@nginx.com     rt = task->thread->runtime;
6011547Smax.romanov@nginx.com 
6021547Smax.romanov@nginx.com     /*
6031547Smax.romanov@nginx.com      * It is safe to access 'runtime->ports' hash because 'NEW_PORT'
6041547Smax.romanov@nginx.com      * sent to main port (with id == 0) and processed in main thread.
6051547Smax.romanov@nginx.com      */
6061547Smax.romanov@nginx.com     main_app_port = nxt_port_hash_find(&rt->ports, port->pid, 0);
6071547Smax.romanov@nginx.com     nxt_assert(main_app_port != NULL);
6081547Smax.romanov@nginx.com 
6091547Smax.romanov@nginx.com     app = main_app_port->app;
6101547Smax.romanov@nginx.com     nxt_assert(app != NULL);
6111547Smax.romanov@nginx.com 
6121547Smax.romanov@nginx.com     nxt_thread_mutex_lock(&app->mutex);
6131547Smax.romanov@nginx.com 
6141547Smax.romanov@nginx.com     /* TODO here should be find-and-add code because there can be
6151547Smax.romanov@nginx.com        port waiters in port_hash */
6161547Smax.romanov@nginx.com     nxt_port_hash_add(&app->port_hash, port);
6171547Smax.romanov@nginx.com     app->port_hash_count++;
6181547Smax.romanov@nginx.com 
6191547Smax.romanov@nginx.com     nxt_thread_mutex_unlock(&app->mutex);
6201547Smax.romanov@nginx.com 
6211547Smax.romanov@nginx.com     port->app = app;
6221547Smax.romanov@nginx.com     port->main_app_port = main_app_port;
623141Smax.romanov@nginx.com }
624141Smax.romanov@nginx.com 
625141Smax.romanov@nginx.com 
626139Sigor@sysoev.ru void
627139Sigor@sysoev.ru nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
628115Sigor@sysoev.ru {
6291526Smax.romanov@nginx.com     void                    *p;
6301526Smax.romanov@nginx.com     size_t                  size;
631198Sigor@sysoev.ru     nxt_int_t               ret;
632139Sigor@sysoev.ru     nxt_router_temp_conf_t  *tmcf;
633139Sigor@sysoev.ru 
634139Sigor@sysoev.ru     tmcf = nxt_router_temp_conf(task);
635139Sigor@sysoev.ru     if (nxt_slow_path(tmcf == NULL)) {
636139Sigor@sysoev.ru         return;
63753Sigor@sysoev.ru     }
63853Sigor@sysoev.ru 
6391526Smax.romanov@nginx.com     if (nxt_slow_path(msg->fd == -1)) {
6401526Smax.romanov@nginx.com         nxt_alert(task, "conf_data_handler: invalid file shm fd");
6411526Smax.romanov@nginx.com         return;
6421526Smax.romanov@nginx.com     }
6431526Smax.romanov@nginx.com 
6441526Smax.romanov@nginx.com     if (nxt_buf_mem_used_size(&msg->buf->mem) != sizeof(size_t)) {
6451526Smax.romanov@nginx.com         nxt_alert(task, "conf_data_handler: unexpected buffer size (%d)",
6461526Smax.romanov@nginx.com                   (int) nxt_buf_mem_used_size(&msg->buf->mem));
6471526Smax.romanov@nginx.com 
6481526Smax.romanov@nginx.com         nxt_fd_close(msg->fd);
6491526Smax.romanov@nginx.com         msg->fd = -1;
6501526Smax.romanov@nginx.com 
6511526Smax.romanov@nginx.com         return;
6521526Smax.romanov@nginx.com     }
6531526Smax.romanov@nginx.com 
6541526Smax.romanov@nginx.com     nxt_memcpy(&size, msg->buf->mem.pos, sizeof(size_t));
6551526Smax.romanov@nginx.com 
6561526Smax.romanov@nginx.com     p = nxt_mem_mmap(NULL, size, PROT_READ, MAP_SHARED, msg->fd, 0);
6571526Smax.romanov@nginx.com 
6581526Smax.romanov@nginx.com     nxt_fd_close(msg->fd);
6591526Smax.romanov@nginx.com     msg->fd = -1;
6601526Smax.romanov@nginx.com 
6611526Smax.romanov@nginx.com     if (nxt_slow_path(p == MAP_FAILED)) {
6621526Smax.romanov@nginx.com         return;
6631526Smax.romanov@nginx.com     }
6641526Smax.romanov@nginx.com 
6651526Smax.romanov@nginx.com     nxt_debug(task, "conf_data_handler(%uz): %*s", size, size, p);
666423Smax.romanov@nginx.com 
667591Sigor@sysoev.ru     tmcf->router_conf->router = nxt_router;
668139Sigor@sysoev.ru     tmcf->stream = msg->port_msg.stream;
669139Sigor@sysoev.ru     tmcf->port = nxt_runtime_port_find(task->thread->runtime,
670198Sigor@sysoev.ru                                        msg->port_msg.pid,
671198Sigor@sysoev.ru                                        msg->port_msg.reply_port);
672198Sigor@sysoev.ru 
673779Smax.romanov@nginx.com     if (nxt_slow_path(tmcf->port == NULL)) {
674779Smax.romanov@nginx.com         nxt_alert(task, "reply port not found");
675779Smax.romanov@nginx.com 
6761526Smax.romanov@nginx.com         goto fail;
677779Smax.romanov@nginx.com     }
678779Smax.romanov@nginx.com 
679779Smax.romanov@nginx.com     nxt_port_use(task, tmcf->port, 1);
680779Smax.romanov@nginx.com 
6811526Smax.romanov@nginx.com     ret = nxt_router_conf_create(task, tmcf, p, nxt_pointer_to(p, size));
682198Sigor@sysoev.ru 
683198Sigor@sysoev.ru     if (nxt_fast_path(ret == NXT_OK)) {
684198Sigor@sysoev.ru         nxt_router_conf_apply(task, tmcf, NULL);
685198Sigor@sysoev.ru 
686198Sigor@sysoev.ru     } else {
687198Sigor@sysoev.ru         nxt_router_conf_error(task, tmcf);
688139Sigor@sysoev.ru     }
6891526Smax.romanov@nginx.com 
6901526Smax.romanov@nginx.com fail:
6911526Smax.romanov@nginx.com 
6921526Smax.romanov@nginx.com     nxt_mem_munmap(p, size);
69353Sigor@sysoev.ru }
69453Sigor@sysoev.ru 
69553Sigor@sysoev.ru 
696347Smax.romanov@nginx.com static void
697507Smax.romanov@nginx.com nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port,
698507Smax.romanov@nginx.com     void *data)
699347Smax.romanov@nginx.com {
700347Smax.romanov@nginx.com     union {
701347Smax.romanov@nginx.com         nxt_pid_t  removed_pid;
702347Smax.romanov@nginx.com         void       *data;
703347Smax.romanov@nginx.com     } u;
704347Smax.romanov@nginx.com 
705347Smax.romanov@nginx.com     u.data = data;
706347Smax.romanov@nginx.com 
707347Smax.romanov@nginx.com     nxt_port_rpc_remove_peer(task, port, u.removed_pid);
708347Smax.romanov@nginx.com }
709347Smax.romanov@nginx.com 
710347Smax.romanov@nginx.com 
711192Smax.romanov@nginx.com void
712192Smax.romanov@nginx.com nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg)
713192Smax.romanov@nginx.com {
714347Smax.romanov@nginx.com     nxt_event_engine_t  *engine;
715318Smax.romanov@nginx.com 
716192Smax.romanov@nginx.com     nxt_port_remove_pid_handler(task, msg);
717192Smax.romanov@nginx.com 
718318Smax.romanov@nginx.com     nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0)
719318Smax.romanov@nginx.com     {
7201486Smax.romanov@nginx.com         if (nxt_fast_path(engine->port != NULL)) {
7211486Smax.romanov@nginx.com             nxt_port_post(task, engine->port, nxt_router_app_process_remove_pid,
7221486Smax.romanov@nginx.com                           msg->u.data);
7231486Smax.romanov@nginx.com         }
724318Smax.romanov@nginx.com     }
725