xref: /aosp_15_r20/external/libwebsockets/lib/plat/unix/unix-spawn.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker  * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker  *
4*1c60b9acSAndroid Build Coastguard Worker  * Copyright (C) 2010 - 2020 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker  *
6*1c60b9acSAndroid Build Coastguard Worker  * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker  * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker  * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker  * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker  * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker  *
13*1c60b9acSAndroid Build Coastguard Worker  * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker  * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker  *
16*1c60b9acSAndroid Build Coastguard Worker  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker  * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker  */
24*1c60b9acSAndroid Build Coastguard Worker 
25*1c60b9acSAndroid Build Coastguard Worker #if !defined(_GNU_SOURCE)
26*1c60b9acSAndroid Build Coastguard Worker #define _GNU_SOURCE
27*1c60b9acSAndroid Build Coastguard Worker #endif
28*1c60b9acSAndroid Build Coastguard Worker 
29*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
30*1c60b9acSAndroid Build Coastguard Worker #include <unistd.h>
31*1c60b9acSAndroid Build Coastguard Worker 
32*1c60b9acSAndroid Build Coastguard Worker #if defined(__OpenBSD__) || defined(__NetBSD__)
33*1c60b9acSAndroid Build Coastguard Worker #include <sys/resource.h>
34*1c60b9acSAndroid Build Coastguard Worker #include <sys/wait.h>
35*1c60b9acSAndroid Build Coastguard Worker #endif
36*1c60b9acSAndroid Build Coastguard Worker 
37*1c60b9acSAndroid Build Coastguard Worker void
lws_spawn_timeout(struct lws_sorted_usec_list * sul)38*1c60b9acSAndroid Build Coastguard Worker lws_spawn_timeout(struct lws_sorted_usec_list *sul)
39*1c60b9acSAndroid Build Coastguard Worker {
40*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped *lsp = lws_container_of(sul,
41*1c60b9acSAndroid Build Coastguard Worker 					struct lws_spawn_piped, sul);
42*1c60b9acSAndroid Build Coastguard Worker 
43*1c60b9acSAndroid Build Coastguard Worker 	lwsl_warn("%s: spawn exceeded timeout, killing\n", __func__);
44*1c60b9acSAndroid Build Coastguard Worker 
45*1c60b9acSAndroid Build Coastguard Worker 	lws_spawn_piped_kill_child_process(lsp);
46*1c60b9acSAndroid Build Coastguard Worker }
47*1c60b9acSAndroid Build Coastguard Worker 
48*1c60b9acSAndroid Build Coastguard Worker void
lws_spawn_sul_reap(struct lws_sorted_usec_list * sul)49*1c60b9acSAndroid Build Coastguard Worker lws_spawn_sul_reap(struct lws_sorted_usec_list *sul)
50*1c60b9acSAndroid Build Coastguard Worker {
51*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped *lsp = lws_container_of(sul,
52*1c60b9acSAndroid Build Coastguard Worker 					struct lws_spawn_piped, sul_reap);
53*1c60b9acSAndroid Build Coastguard Worker 
54*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: reaping spawn after last stdpipe, tries left %d\n",
55*1c60b9acSAndroid Build Coastguard Worker 		    __func__, lsp->reap_retry_budget);
56*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_spawn_reap(lsp) && !lsp->pipes_alive) {
57*1c60b9acSAndroid Build Coastguard Worker 		if (--lsp->reap_retry_budget) {
58*1c60b9acSAndroid Build Coastguard Worker 			lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
59*1c60b9acSAndroid Build Coastguard Worker 					 &lsp->sul_reap, lws_spawn_sul_reap,
60*1c60b9acSAndroid Build Coastguard Worker 					 250 * LWS_US_PER_MS);
61*1c60b9acSAndroid Build Coastguard Worker 		} else {
62*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: Unable to reap lsp %p, killing\n",
63*1c60b9acSAndroid Build Coastguard Worker 				 __func__, lsp);
64*1c60b9acSAndroid Build Coastguard Worker 			lsp->reap_retry_budget = 20;
65*1c60b9acSAndroid Build Coastguard Worker 			lws_spawn_piped_kill_child_process(lsp);
66*1c60b9acSAndroid Build Coastguard Worker 		}
67*1c60b9acSAndroid Build Coastguard Worker 	}
68*1c60b9acSAndroid Build Coastguard Worker }
69*1c60b9acSAndroid Build Coastguard Worker 
70*1c60b9acSAndroid Build Coastguard Worker static struct lws *
lws_create_stdwsi(struct lws_context * context,int tsi,const struct lws_role_ops * ops)71*1c60b9acSAndroid Build Coastguard Worker lws_create_stdwsi(struct lws_context *context, int tsi,
72*1c60b9acSAndroid Build Coastguard Worker 		     const struct lws_role_ops *ops)
73*1c60b9acSAndroid Build Coastguard Worker {
74*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[tsi];
75*1c60b9acSAndroid Build Coastguard Worker 	struct lws *new_wsi;
76*1c60b9acSAndroid Build Coastguard Worker 
77*1c60b9acSAndroid Build Coastguard Worker 	if (!context->vhost_list)
78*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
79*1c60b9acSAndroid Build Coastguard Worker 
80*1c60b9acSAndroid Build Coastguard Worker 	if ((unsigned int)pt->fds_count == context->fd_limit_per_thread - 1) {
81*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("no space for new conn\n");
82*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
83*1c60b9acSAndroid Build Coastguard Worker 	}
84*1c60b9acSAndroid Build Coastguard Worker 
85*1c60b9acSAndroid Build Coastguard Worker 	lws_context_lock(context, __func__);
86*1c60b9acSAndroid Build Coastguard Worker 	new_wsi = __lws_wsi_create_with_role(context, tsi, ops, NULL);
87*1c60b9acSAndroid Build Coastguard Worker 	lws_context_unlock(context);
88*1c60b9acSAndroid Build Coastguard Worker 	if (new_wsi == NULL) {
89*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("Out of memory for new connection\n");
90*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
91*1c60b9acSAndroid Build Coastguard Worker 	}
92*1c60b9acSAndroid Build Coastguard Worker 
93*1c60b9acSAndroid Build Coastguard Worker 	new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
94*1c60b9acSAndroid Build Coastguard Worker 
95*1c60b9acSAndroid Build Coastguard Worker 	/* initialize the instance struct */
96*1c60b9acSAndroid Build Coastguard Worker 
97*1c60b9acSAndroid Build Coastguard Worker 	lws_role_transition(new_wsi, 0, LRS_ESTABLISHED, ops);
98*1c60b9acSAndroid Build Coastguard Worker 
99*1c60b9acSAndroid Build Coastguard Worker 	new_wsi->hdr_parsing_completed = 0;
100*1c60b9acSAndroid Build Coastguard Worker 
101*1c60b9acSAndroid Build Coastguard Worker 	/*
102*1c60b9acSAndroid Build Coastguard Worker 	 * these can only be set once the protocol is known
103*1c60b9acSAndroid Build Coastguard Worker 	 * we set an unestablished connection's protocol pointer
104*1c60b9acSAndroid Build Coastguard Worker 	 * to the start of the defauly vhost supported list, so it can look
105*1c60b9acSAndroid Build Coastguard Worker 	 * for matching ones during the handshake
106*1c60b9acSAndroid Build Coastguard Worker 	 */
107*1c60b9acSAndroid Build Coastguard Worker 
108*1c60b9acSAndroid Build Coastguard Worker 	new_wsi->user_space = NULL;
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker 	return new_wsi;
111*1c60b9acSAndroid Build Coastguard Worker }
112*1c60b9acSAndroid Build Coastguard Worker 
113*1c60b9acSAndroid Build Coastguard Worker void
lws_spawn_piped_destroy(struct lws_spawn_piped ** _lsp)114*1c60b9acSAndroid Build Coastguard Worker lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp)
115*1c60b9acSAndroid Build Coastguard Worker {
116*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped *lsp = *_lsp;
117*1c60b9acSAndroid Build Coastguard Worker 	int n;
118*1c60b9acSAndroid Build Coastguard Worker 
119*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp)
120*1c60b9acSAndroid Build Coastguard Worker 		return;
121*1c60b9acSAndroid Build Coastguard Worker 
122*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_remove(&lsp->dll);
123*1c60b9acSAndroid Build Coastguard Worker 
124*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_cancel(&lsp->sul);
125*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_cancel(&lsp->sul_reap);
126*1c60b9acSAndroid Build Coastguard Worker 
127*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
128*1c60b9acSAndroid Build Coastguard Worker #if 0
129*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->pipe_fds[n][!!(n == 0)] == 0)
130*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("ZERO FD IN CGI CLOSE");
131*1c60b9acSAndroid Build Coastguard Worker 
132*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->pipe_fds[n][!!(n == 0)] >= 0) {
133*1c60b9acSAndroid Build Coastguard Worker 			close(lsp->pipe_fds[n][!!(n == 0)]);
134*1c60b9acSAndroid Build Coastguard Worker 			lsp->pipe_fds[n][!!(n == 0)] = LWS_SOCK_INVALID;
135*1c60b9acSAndroid Build Coastguard Worker 		}
136*1c60b9acSAndroid Build Coastguard Worker #endif
137*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->stdwsi[n]) {
138*1c60b9acSAndroid Build Coastguard Worker 			lws_set_timeout(lsp->stdwsi[n], 1, LWS_TO_KILL_ASYNC);
139*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[n] = NULL;
140*1c60b9acSAndroid Build Coastguard Worker 		}
141*1c60b9acSAndroid Build Coastguard Worker 	}
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker 	lws_free_set_NULL((*_lsp));
144*1c60b9acSAndroid Build Coastguard Worker }
145*1c60b9acSAndroid Build Coastguard Worker 
146*1c60b9acSAndroid Build Coastguard Worker int
lws_spawn_reap(struct lws_spawn_piped * lsp)147*1c60b9acSAndroid Build Coastguard Worker lws_spawn_reap(struct lws_spawn_piped *lsp)
148*1c60b9acSAndroid Build Coastguard Worker {
149*1c60b9acSAndroid Build Coastguard Worker 	long hz = sysconf(_SC_CLK_TCK); /* accounting Hz */
150*1c60b9acSAndroid Build Coastguard Worker 	void *opaque = lsp->info.opaque;
151*1c60b9acSAndroid Build Coastguard Worker 	lsp_cb_t cb = lsp->info.reap_cb;
152*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped temp;
153*1c60b9acSAndroid Build Coastguard Worker 	struct tms tms;
154*1c60b9acSAndroid Build Coastguard Worker #if defined(__OpenBSD__) || defined(__NetBSD__)
155*1c60b9acSAndroid Build Coastguard Worker 	struct rusage rusa;
156*1c60b9acSAndroid Build Coastguard Worker 	int status;
157*1c60b9acSAndroid Build Coastguard Worker #endif
158*1c60b9acSAndroid Build Coastguard Worker 	int n;
159*1c60b9acSAndroid Build Coastguard Worker 
160*1c60b9acSAndroid Build Coastguard Worker 	if (lsp->child_pid < 1)
161*1c60b9acSAndroid Build Coastguard Worker 		return 0;
162*1c60b9acSAndroid Build Coastguard Worker 
163*1c60b9acSAndroid Build Coastguard Worker 	/* check if exited, do not reap yet */
164*1c60b9acSAndroid Build Coastguard Worker 
165*1c60b9acSAndroid Build Coastguard Worker 	memset(&lsp->si, 0, sizeof(lsp->si));
166*1c60b9acSAndroid Build Coastguard Worker #if defined(__OpenBSD__) || defined(__NetBSD__)
167*1c60b9acSAndroid Build Coastguard Worker 	n = wait4(lsp->child_pid, &status, WNOHANG, &rusa);
168*1c60b9acSAndroid Build Coastguard Worker 	if (!n)
169*1c60b9acSAndroid Build Coastguard Worker 		return 0;
170*1c60b9acSAndroid Build Coastguard Worker 	lsp->si.si_code = WIFEXITED(status);
171*1c60b9acSAndroid Build Coastguard Worker #else
172*1c60b9acSAndroid Build Coastguard Worker 	n = waitid(P_PID, (id_t)lsp->child_pid, &lsp->si, WEXITED | WNOHANG | WNOWAIT);
173*1c60b9acSAndroid Build Coastguard Worker #endif
174*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
175*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: child %d still running\n", __func__, lsp->child_pid);
176*1c60b9acSAndroid Build Coastguard Worker 		return 0;
177*1c60b9acSAndroid Build Coastguard Worker 	}
178*1c60b9acSAndroid Build Coastguard Worker 
179*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->si.si_code)
180*1c60b9acSAndroid Build Coastguard Worker 		return 0;
181*1c60b9acSAndroid Build Coastguard Worker 
182*1c60b9acSAndroid Build Coastguard Worker 	/* his process has exited... */
183*1c60b9acSAndroid Build Coastguard Worker 
184*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->reaped) {
185*1c60b9acSAndroid Build Coastguard Worker 		/* mark the earliest time we knew he had gone */
186*1c60b9acSAndroid Build Coastguard Worker 		lsp->reaped = lws_now_usecs();
187*1c60b9acSAndroid Build Coastguard Worker 
188*1c60b9acSAndroid Build Coastguard Worker 		/*
189*1c60b9acSAndroid Build Coastguard Worker 		 * Switch the timeout to restrict the amount of grace time
190*1c60b9acSAndroid Build Coastguard Worker 		 * to drain stdwsi
191*1c60b9acSAndroid Build Coastguard Worker 		 */
192*1c60b9acSAndroid Build Coastguard Worker 
193*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
194*1c60b9acSAndroid Build Coastguard Worker 				 &lsp->sul, lws_spawn_timeout,
195*1c60b9acSAndroid Build Coastguard Worker 				 5 * LWS_US_PER_SEC);
196*1c60b9acSAndroid Build Coastguard Worker 	}
197*1c60b9acSAndroid Build Coastguard Worker 
198*1c60b9acSAndroid Build Coastguard Worker 	/*
199*1c60b9acSAndroid Build Coastguard Worker 	 * Stage finalizing our reaction to the process going down until the
200*1c60b9acSAndroid Build Coastguard Worker 	 * stdwsi flushed whatever is in flight and all noticed they were
201*1c60b9acSAndroid Build Coastguard Worker 	 * closed.  For that reason, each stdwsi close must call lws_spawn_reap
202*1c60b9acSAndroid Build Coastguard Worker 	 * to check if that was the last one and we can proceed with the reap.
203*1c60b9acSAndroid Build Coastguard Worker 	 */
204*1c60b9acSAndroid Build Coastguard Worker 
205*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->ungraceful && lsp->pipes_alive) {
206*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: %d stdwsi alive, not reaping\n", __func__,
207*1c60b9acSAndroid Build Coastguard Worker 				lsp->pipes_alive);
208*1c60b9acSAndroid Build Coastguard Worker 		return 0;
209*1c60b9acSAndroid Build Coastguard Worker 	}
210*1c60b9acSAndroid Build Coastguard Worker 
211*1c60b9acSAndroid Build Coastguard Worker 	/* we reached the reap point, no need for timeout wait */
212*1c60b9acSAndroid Build Coastguard Worker 
213*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_cancel(&lsp->sul);
214*1c60b9acSAndroid Build Coastguard Worker 
215*1c60b9acSAndroid Build Coastguard Worker 	/*
216*1c60b9acSAndroid Build Coastguard Worker 	 * All the stdwsi went down, nothing more is coming... it's over
217*1c60b9acSAndroid Build Coastguard Worker 	 * Collect the final information and then reap the dead process
218*1c60b9acSAndroid Build Coastguard Worker 	 */
219*1c60b9acSAndroid Build Coastguard Worker 
220*1c60b9acSAndroid Build Coastguard Worker 	if (times(&tms) != (clock_t) -1) {
221*1c60b9acSAndroid Build Coastguard Worker 		/*
222*1c60b9acSAndroid Build Coastguard Worker 		 * Cpu accounting in us
223*1c60b9acSAndroid Build Coastguard Worker 		 */
224*1c60b9acSAndroid Build Coastguard Worker 		lsp->accounting[0] = (lws_usec_t)((uint64_t)tms.tms_cstime * 1000000) / hz;
225*1c60b9acSAndroid Build Coastguard Worker 		lsp->accounting[1] = (lws_usec_t)((uint64_t)tms.tms_cutime * 1000000) / hz;
226*1c60b9acSAndroid Build Coastguard Worker 		lsp->accounting[2] = (lws_usec_t)((uint64_t)tms.tms_stime * 1000000) / hz;
227*1c60b9acSAndroid Build Coastguard Worker 		lsp->accounting[3] = (lws_usec_t)((uint64_t)tms.tms_utime * 1000000) / hz;
228*1c60b9acSAndroid Build Coastguard Worker 	}
229*1c60b9acSAndroid Build Coastguard Worker 
230*1c60b9acSAndroid Build Coastguard Worker 	temp = *lsp;
231*1c60b9acSAndroid Build Coastguard Worker #if defined(__OpenBSD__) || defined(__NetBSD__)
232*1c60b9acSAndroid Build Coastguard Worker 	n = wait4(lsp->child_pid, &status, WNOHANG, &rusa);
233*1c60b9acSAndroid Build Coastguard Worker 	if (!n)
234*1c60b9acSAndroid Build Coastguard Worker 		return 0;
235*1c60b9acSAndroid Build Coastguard Worker 	lsp->si.si_code = WIFEXITED(status);
236*1c60b9acSAndroid Build Coastguard Worker 	if (lsp->si.si_code == CLD_EXITED)
237*1c60b9acSAndroid Build Coastguard Worker 		temp.si.si_code = CLD_EXITED;
238*1c60b9acSAndroid Build Coastguard Worker 	temp.si.si_status = WEXITSTATUS(status);
239*1c60b9acSAndroid Build Coastguard Worker #else
240*1c60b9acSAndroid Build Coastguard Worker 	n = waitid(P_PID, (id_t)lsp->child_pid, &temp.si, WEXITED | WNOHANG);
241*1c60b9acSAndroid Build Coastguard Worker #endif
242*1c60b9acSAndroid Build Coastguard Worker 	temp.si.si_status &= 0xff; /* we use b8 + for flags */
243*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: waitd says %d, process exit %d\n",
244*1c60b9acSAndroid Build Coastguard Worker 		    __func__, n, temp.si.si_status);
245*1c60b9acSAndroid Build Coastguard Worker 
246*1c60b9acSAndroid Build Coastguard Worker 	lsp->child_pid = -1;
247*1c60b9acSAndroid Build Coastguard Worker 
248*1c60b9acSAndroid Build Coastguard Worker 	/* destroy the lsp itself first (it's freed and plsp set NULL */
249*1c60b9acSAndroid Build Coastguard Worker 
250*1c60b9acSAndroid Build Coastguard Worker 	if (lsp->info.plsp)
251*1c60b9acSAndroid Build Coastguard Worker 		lws_spawn_piped_destroy(lsp->info.plsp);
252*1c60b9acSAndroid Build Coastguard Worker 
253*1c60b9acSAndroid Build Coastguard Worker 	/* then do the parent callback informing it's destroyed */
254*1c60b9acSAndroid Build Coastguard Worker 
255*1c60b9acSAndroid Build Coastguard Worker 	if (cb)
256*1c60b9acSAndroid Build Coastguard Worker 		cb(opaque, temp.accounting, &temp.si,
257*1c60b9acSAndroid Build Coastguard Worker 		   temp.we_killed_him_timeout |
258*1c60b9acSAndroid Build Coastguard Worker 			   (temp.we_killed_him_spew << 1));
259*1c60b9acSAndroid Build Coastguard Worker 
260*1c60b9acSAndroid Build Coastguard Worker 	return 1; /* was reaped */
261*1c60b9acSAndroid Build Coastguard Worker }
262*1c60b9acSAndroid Build Coastguard Worker 
263*1c60b9acSAndroid Build Coastguard Worker int
lws_spawn_piped_kill_child_process(struct lws_spawn_piped * lsp)264*1c60b9acSAndroid Build Coastguard Worker lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp)
265*1c60b9acSAndroid Build Coastguard Worker {
266*1c60b9acSAndroid Build Coastguard Worker 	int status, n;
267*1c60b9acSAndroid Build Coastguard Worker 
268*1c60b9acSAndroid Build Coastguard Worker 	if (lsp->child_pid <= 0)
269*1c60b9acSAndroid Build Coastguard Worker 		return 1;
270*1c60b9acSAndroid Build Coastguard Worker 
271*1c60b9acSAndroid Build Coastguard Worker 	lsp->ungraceful = 1; /* don't wait for flushing, just kill it */
272*1c60b9acSAndroid Build Coastguard Worker 
273*1c60b9acSAndroid Build Coastguard Worker 	if (lws_spawn_reap(lsp))
274*1c60b9acSAndroid Build Coastguard Worker 		/* that may have invalidated lsp */
275*1c60b9acSAndroid Build Coastguard Worker 		return 0;
276*1c60b9acSAndroid Build Coastguard Worker 
277*1c60b9acSAndroid Build Coastguard Worker 	/* kill the process group */
278*1c60b9acSAndroid Build Coastguard Worker 	n = kill(-lsp->child_pid, SIGTERM);
279*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: SIGTERM child PID %d says %d (errno %d)\n", __func__,
280*1c60b9acSAndroid Build Coastguard Worker 		   lsp->child_pid, n, errno);
281*1c60b9acSAndroid Build Coastguard Worker 	if (n < 0) {
282*1c60b9acSAndroid Build Coastguard Worker 		/*
283*1c60b9acSAndroid Build Coastguard Worker 		 * hum seen errno=3 when process is listed in ps,
284*1c60b9acSAndroid Build Coastguard Worker 		 * it seems we don't always retain process grouping
285*1c60b9acSAndroid Build Coastguard Worker 		 *
286*1c60b9acSAndroid Build Coastguard Worker 		 * Direct these fallback attempt to the exact child
287*1c60b9acSAndroid Build Coastguard Worker 		 */
288*1c60b9acSAndroid Build Coastguard Worker 		n = kill(lsp->child_pid, SIGTERM);
289*1c60b9acSAndroid Build Coastguard Worker 		if (n < 0) {
290*1c60b9acSAndroid Build Coastguard Worker 			n = kill(lsp->child_pid, SIGPIPE);
291*1c60b9acSAndroid Build Coastguard Worker 			if (n < 0) {
292*1c60b9acSAndroid Build Coastguard Worker 				n = kill(lsp->child_pid, SIGKILL);
293*1c60b9acSAndroid Build Coastguard Worker 				if (n < 0)
294*1c60b9acSAndroid Build Coastguard Worker 					lwsl_info("%s: SIGKILL PID %d "
295*1c60b9acSAndroid Build Coastguard Worker 						 "failed errno %d "
296*1c60b9acSAndroid Build Coastguard Worker 						 "(maybe zombie)\n", __func__,
297*1c60b9acSAndroid Build Coastguard Worker 						 lsp->child_pid, errno);
298*1c60b9acSAndroid Build Coastguard Worker 			}
299*1c60b9acSAndroid Build Coastguard Worker 		}
300*1c60b9acSAndroid Build Coastguard Worker 	}
301*1c60b9acSAndroid Build Coastguard Worker 
302*1c60b9acSAndroid Build Coastguard Worker 	/* He could be unkillable because he's a zombie */
303*1c60b9acSAndroid Build Coastguard Worker 
304*1c60b9acSAndroid Build Coastguard Worker 	n = 1;
305*1c60b9acSAndroid Build Coastguard Worker 	while (n > 0) {
306*1c60b9acSAndroid Build Coastguard Worker 		n = waitpid(-lsp->child_pid, &status, WNOHANG);
307*1c60b9acSAndroid Build Coastguard Worker 		if (n > 0)
308*1c60b9acSAndroid Build Coastguard Worker 			lwsl_debug("%s: reaped PID %d\n", __func__, n);
309*1c60b9acSAndroid Build Coastguard Worker 		if (n <= 0) {
310*1c60b9acSAndroid Build Coastguard Worker 			n = waitpid(lsp->child_pid, &status, WNOHANG);
311*1c60b9acSAndroid Build Coastguard Worker 			if (n > 0)
312*1c60b9acSAndroid Build Coastguard Worker 				lwsl_debug("%s: reaped PID %d\n", __func__, n);
313*1c60b9acSAndroid Build Coastguard Worker 		}
314*1c60b9acSAndroid Build Coastguard Worker 	}
315*1c60b9acSAndroid Build Coastguard Worker 
316*1c60b9acSAndroid Build Coastguard Worker 	lws_spawn_reap(lsp);
317*1c60b9acSAndroid Build Coastguard Worker 	/* that may have invalidated lsp */
318*1c60b9acSAndroid Build Coastguard Worker 
319*1c60b9acSAndroid Build Coastguard Worker 	return 0;
320*1c60b9acSAndroid Build Coastguard Worker }
321*1c60b9acSAndroid Build Coastguard Worker 
322*1c60b9acSAndroid Build Coastguard Worker /*
323*1c60b9acSAndroid Build Coastguard Worker  * Deals with spawning a subprocess and executing it securely with stdin/out/err
324*1c60b9acSAndroid Build Coastguard Worker  * diverted into pipes
325*1c60b9acSAndroid Build Coastguard Worker  */
326*1c60b9acSAndroid Build Coastguard Worker 
327*1c60b9acSAndroid Build Coastguard Worker struct lws_spawn_piped *
lws_spawn_piped(const struct lws_spawn_piped_info * i)328*1c60b9acSAndroid Build Coastguard Worker lws_spawn_piped(const struct lws_spawn_piped_info *i)
329*1c60b9acSAndroid Build Coastguard Worker {
330*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_protocols *pcol = i->vh->context->vhost_list->protocols;
331*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context = i->vh->context;
332*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped *lsp;
333*1c60b9acSAndroid Build Coastguard Worker 	const char *wd;
334*1c60b9acSAndroid Build Coastguard Worker 	int n, m;
335*1c60b9acSAndroid Build Coastguard Worker 
336*1c60b9acSAndroid Build Coastguard Worker 	if (i->protocol_name)
337*1c60b9acSAndroid Build Coastguard Worker 		pcol = lws_vhost_name_to_protocol(i->vh, i->protocol_name);
338*1c60b9acSAndroid Build Coastguard Worker 	if (!pcol) {
339*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unknown protocol %s\n", __func__,
340*1c60b9acSAndroid Build Coastguard Worker 			 i->protocol_name ? i->protocol_name : "default");
341*1c60b9acSAndroid Build Coastguard Worker 
342*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
343*1c60b9acSAndroid Build Coastguard Worker 	}
344*1c60b9acSAndroid Build Coastguard Worker 
345*1c60b9acSAndroid Build Coastguard Worker 	lsp = lws_zalloc(sizeof(*lsp), __func__);
346*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp)
347*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
348*1c60b9acSAndroid Build Coastguard Worker 
349*1c60b9acSAndroid Build Coastguard Worker 	/* wholesale take a copy of info */
350*1c60b9acSAndroid Build Coastguard Worker 	lsp->info = *i;
351*1c60b9acSAndroid Build Coastguard Worker 	lsp->reap_retry_budget = 20;
352*1c60b9acSAndroid Build Coastguard Worker 
353*1c60b9acSAndroid Build Coastguard Worker 	/*
354*1c60b9acSAndroid Build Coastguard Worker 	 * Prepare the stdin / out / err pipes
355*1c60b9acSAndroid Build Coastguard Worker 	 */
356*1c60b9acSAndroid Build Coastguard Worker 
357*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
358*1c60b9acSAndroid Build Coastguard Worker 		lsp->pipe_fds[n][0] = -1;
359*1c60b9acSAndroid Build Coastguard Worker 		lsp->pipe_fds[n][1] = -1;
360*1c60b9acSAndroid Build Coastguard Worker 	}
361*1c60b9acSAndroid Build Coastguard Worker 
362*1c60b9acSAndroid Build Coastguard Worker 	/* create pipes for [stdin|stdout] and [stderr] */
363*1c60b9acSAndroid Build Coastguard Worker 
364*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
365*1c60b9acSAndroid Build Coastguard Worker 		if (pipe(lsp->pipe_fds[n]) == -1)
366*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
367*1c60b9acSAndroid Build Coastguard Worker 		lws_plat_apply_FD_CLOEXEC(lsp->pipe_fds[n][n == 0]);
368*1c60b9acSAndroid Build Coastguard Worker 	}
369*1c60b9acSAndroid Build Coastguard Worker 
370*1c60b9acSAndroid Build Coastguard Worker 	/*
371*1c60b9acSAndroid Build Coastguard Worker 	 * At this point, we have 6 pipe fds open on lws side and no wsis
372*1c60b9acSAndroid Build Coastguard Worker 	 * bound to them
373*1c60b9acSAndroid Build Coastguard Worker 	 */
374*1c60b9acSAndroid Build Coastguard Worker 
375*1c60b9acSAndroid Build Coastguard Worker 	/* create wsis for each stdin/out/err fd */
376*1c60b9acSAndroid Build Coastguard Worker 
377*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
378*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n] = lws_create_stdwsi(i->vh->context, i->tsi,
379*1c60b9acSAndroid Build Coastguard Worker 					  i->ops ? i->ops : &role_ops_raw_file);
380*1c60b9acSAndroid Build Coastguard Worker 		if (!lsp->stdwsi[n]) {
381*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable to create lsp stdwsi\n", __func__);
382*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
383*1c60b9acSAndroid Build Coastguard Worker 		}
384*1c60b9acSAndroid Build Coastguard Worker 
385*1c60b9acSAndroid Build Coastguard Worker                 __lws_lc_tag(i->vh->context, &i->vh->context->lcg[LWSLCG_WSI],
386*1c60b9acSAndroid Build Coastguard Worker                 	     &lsp->stdwsi[n]->lc, "nspawn-stdwsi-%d", n);
387*1c60b9acSAndroid Build Coastguard Worker 
388*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->lsp_channel = (uint8_t)n;
389*1c60b9acSAndroid Build Coastguard Worker 		lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]);
390*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->a.protocol = pcol;
391*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->a.opaque_user_data = i->opaque;
392*1c60b9acSAndroid Build Coastguard Worker 
393*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n", __func__,
394*1c60b9acSAndroid Build Coastguard Worker 			   lsp->stdwsi[n], n, lsp->pipe_fds[n][n == 0],
395*1c60b9acSAndroid Build Coastguard Worker 			   lsp->pipe_fds[n][n != 0]);
396*1c60b9acSAndroid Build Coastguard Worker 
397*1c60b9acSAndroid Build Coastguard Worker 		/* read side is 0, stdin we want the write side, others read */
398*1c60b9acSAndroid Build Coastguard Worker 
399*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->desc.sockfd = lsp->pipe_fds[n][n == 0];
400*1c60b9acSAndroid Build Coastguard Worker 		if (fcntl(lsp->pipe_fds[n][n == 0], F_SETFL, O_NONBLOCK) < 0) {
401*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: setting NONBLOCK failed\n", __func__);
402*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
403*1c60b9acSAndroid Build Coastguard Worker 		}
404*1c60b9acSAndroid Build Coastguard Worker 
405*1c60b9acSAndroid Build Coastguard Worker 		/*
406*1c60b9acSAndroid Build Coastguard Worker 		 * We have bound 3 x pipe fds to wsis, wr side of stdin and rd
407*1c60b9acSAndroid Build Coastguard Worker 		 * side of stdout / stderr... those are marked CLOEXEC so they
408*1c60b9acSAndroid Build Coastguard Worker 		 * won't go through the fork
409*1c60b9acSAndroid Build Coastguard Worker 		 *
410*1c60b9acSAndroid Build Coastguard Worker 		 * rd side of stdin and wr side of stdout / stderr are open but
411*1c60b9acSAndroid Build Coastguard Worker 		 * not bound to anything on lws side.
412*1c60b9acSAndroid Build Coastguard Worker 		 */
413*1c60b9acSAndroid Build Coastguard Worker 	}
414*1c60b9acSAndroid Build Coastguard Worker 
415*1c60b9acSAndroid Build Coastguard Worker 	/*
416*1c60b9acSAndroid Build Coastguard Worker 	 * Stitch the wsi fd into the poll wait
417*1c60b9acSAndroid Build Coastguard Worker 	 */
418*1c60b9acSAndroid Build Coastguard Worker 
419*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
420*1c60b9acSAndroid Build Coastguard Worker 		if (context->event_loop_ops->sock_accept)
421*1c60b9acSAndroid Build Coastguard Worker 			if (context->event_loop_ops->sock_accept(lsp->stdwsi[n]))
422*1c60b9acSAndroid Build Coastguard Worker 				goto bail3;
423*1c60b9acSAndroid Build Coastguard Worker 
424*1c60b9acSAndroid Build Coastguard Worker 		if (__insert_wsi_socket_into_fds(context, lsp->stdwsi[n]))
425*1c60b9acSAndroid Build Coastguard Worker 			goto bail3;
426*1c60b9acSAndroid Build Coastguard Worker 		if (i->opt_parent) {
427*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[n]->parent = i->opt_parent;
428*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[n]->sibling_list = i->opt_parent->child_list;
429*1c60b9acSAndroid Build Coastguard Worker 			i->opt_parent->child_list = lsp->stdwsi[n];
430*1c60b9acSAndroid Build Coastguard Worker 		}
431*1c60b9acSAndroid Build Coastguard Worker 	}
432*1c60b9acSAndroid Build Coastguard Worker 
433*1c60b9acSAndroid Build Coastguard Worker 	if (lws_change_pollfd(lsp->stdwsi[LWS_STDIN], LWS_POLLIN, LWS_POLLOUT))
434*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
435*1c60b9acSAndroid Build Coastguard Worker 	if (lws_change_pollfd(lsp->stdwsi[LWS_STDOUT], LWS_POLLOUT, LWS_POLLIN))
436*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
437*1c60b9acSAndroid Build Coastguard Worker 	if (lws_change_pollfd(lsp->stdwsi[LWS_STDERR], LWS_POLLOUT, LWS_POLLIN))
438*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
439*1c60b9acSAndroid Build Coastguard Worker 
440*1c60b9acSAndroid Build Coastguard Worker 	lwsl_info("%s: fds in %d, out %d, err %d\n", __func__,
441*1c60b9acSAndroid Build Coastguard Worker 		   lsp->stdwsi[LWS_STDIN]->desc.sockfd,
442*1c60b9acSAndroid Build Coastguard Worker 		   lsp->stdwsi[LWS_STDOUT]->desc.sockfd,
443*1c60b9acSAndroid Build Coastguard Worker 		   lsp->stdwsi[LWS_STDERR]->desc.sockfd);
444*1c60b9acSAndroid Build Coastguard Worker 
445*1c60b9acSAndroid Build Coastguard Worker 	/* we are ready with the redirection pipes... do the (v)fork */
446*1c60b9acSAndroid Build Coastguard Worker #if defined(__sun) || !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE)
447*1c60b9acSAndroid Build Coastguard Worker 	lsp->child_pid = fork();
448*1c60b9acSAndroid Build Coastguard Worker #else
449*1c60b9acSAndroid Build Coastguard Worker 	lsp->child_pid = vfork();
450*1c60b9acSAndroid Build Coastguard Worker #endif
451*1c60b9acSAndroid Build Coastguard Worker 	if (lsp->child_pid < 0) {
452*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: fork failed, errno %d", __func__, errno);
453*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
454*1c60b9acSAndroid Build Coastguard Worker 	}
455*1c60b9acSAndroid Build Coastguard Worker 
456*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__)
457*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->child_pid)
458*1c60b9acSAndroid Build Coastguard Worker 		prctl(PR_SET_PDEATHSIG, SIGTERM);
459*1c60b9acSAndroid Build Coastguard Worker #endif
460*1c60b9acSAndroid Build Coastguard Worker 
461*1c60b9acSAndroid Build Coastguard Worker 	if (lsp->info.disable_ctrlc)
462*1c60b9acSAndroid Build Coastguard Worker 		/* stops non-daemonized main processess getting SIGINT
463*1c60b9acSAndroid Build Coastguard Worker 		 * from TTY */
464*1c60b9acSAndroid Build Coastguard Worker #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
465*1c60b9acSAndroid Build Coastguard Worker 		setpgid(0, 0);
466*1c60b9acSAndroid Build Coastguard Worker #else
467*1c60b9acSAndroid Build Coastguard Worker 		setpgrp();
468*1c60b9acSAndroid Build Coastguard Worker #endif
469*1c60b9acSAndroid Build Coastguard Worker 
470*1c60b9acSAndroid Build Coastguard Worker 	if (lsp->child_pid) {
471*1c60b9acSAndroid Build Coastguard Worker 
472*1c60b9acSAndroid Build Coastguard Worker 		/*
473*1c60b9acSAndroid Build Coastguard Worker 		 * We are the parent process.  We can close our copy of the
474*1c60b9acSAndroid Build Coastguard Worker 		 * "other" side of the pipe fds, ie, rd for stdin and wr for
475*1c60b9acSAndroid Build Coastguard Worker 		 * stdout / stderr.
476*1c60b9acSAndroid Build Coastguard Worker 		 */
477*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < 3; n++)
478*1c60b9acSAndroid Build Coastguard Worker 			/* these guys didn't have any wsi footprint */
479*1c60b9acSAndroid Build Coastguard Worker 			close(lsp->pipe_fds[n][n != 0]);
480*1c60b9acSAndroid Build Coastguard Worker 
481*1c60b9acSAndroid Build Coastguard Worker 		lsp->pipes_alive = 3;
482*1c60b9acSAndroid Build Coastguard Worker 		lsp->created = lws_now_usecs();
483*1c60b9acSAndroid Build Coastguard Worker 
484*1c60b9acSAndroid Build Coastguard Worker 		lwsl_info("%s: lsp %p spawned PID %d\n", __func__, lsp,
485*1c60b9acSAndroid Build Coastguard Worker 			  lsp->child_pid);
486*1c60b9acSAndroid Build Coastguard Worker 
487*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout,
488*1c60b9acSAndroid Build Coastguard Worker 				 i->timeout_us ? i->timeout_us :
489*1c60b9acSAndroid Build Coastguard Worker 						   300 * LWS_US_PER_SEC);
490*1c60b9acSAndroid Build Coastguard Worker 
491*1c60b9acSAndroid Build Coastguard Worker 		if (i->owner)
492*1c60b9acSAndroid Build Coastguard Worker 			lws_dll2_add_head(&lsp->dll, i->owner);
493*1c60b9acSAndroid Build Coastguard Worker 
494*1c60b9acSAndroid Build Coastguard Worker 		if (i->timeout_us)
495*1c60b9acSAndroid Build Coastguard Worker 			lws_sul_schedule(context, i->tsi, &lsp->sul,
496*1c60b9acSAndroid Build Coastguard Worker 					 lws_spawn_timeout, i->timeout_us);
497*1c60b9acSAndroid Build Coastguard Worker 
498*1c60b9acSAndroid Build Coastguard Worker 		return lsp;
499*1c60b9acSAndroid Build Coastguard Worker 	}
500*1c60b9acSAndroid Build Coastguard Worker 
501*1c60b9acSAndroid Build Coastguard Worker 	/*
502*1c60b9acSAndroid Build Coastguard Worker 	 * We are the forked process, redirect and kill inherited things.
503*1c60b9acSAndroid Build Coastguard Worker 	 *
504*1c60b9acSAndroid Build Coastguard Worker 	 * Because of vfork(), we cannot do anything that changes pages in
505*1c60b9acSAndroid Build Coastguard Worker 	 * the parent environment.  Stuff that changes kernel state for the
506*1c60b9acSAndroid Build Coastguard Worker 	 * process is OK.  Stuff that happens after the execvpe() is OK.
507*1c60b9acSAndroid Build Coastguard Worker 	 */
508*1c60b9acSAndroid Build Coastguard Worker 
509*1c60b9acSAndroid Build Coastguard Worker 	if (i->chroot_path && chroot(i->chroot_path)) {
510*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: child chroot %s failed, errno %d\n",
511*1c60b9acSAndroid Build Coastguard Worker 			 __func__, i->chroot_path, errno);
512*1c60b9acSAndroid Build Coastguard Worker 
513*1c60b9acSAndroid Build Coastguard Worker 		exit(2);
514*1c60b9acSAndroid Build Coastguard Worker 	}
515*1c60b9acSAndroid Build Coastguard Worker 
516*1c60b9acSAndroid Build Coastguard Worker 	/* cwd: somewhere we can at least read things and enter it */
517*1c60b9acSAndroid Build Coastguard Worker 
518*1c60b9acSAndroid Build Coastguard Worker 	wd = i->wd;
519*1c60b9acSAndroid Build Coastguard Worker 	if (!wd)
520*1c60b9acSAndroid Build Coastguard Worker 		wd = "/tmp";
521*1c60b9acSAndroid Build Coastguard Worker 	if (chdir(wd))
522*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: Failed to cd to %s\n", __func__, wd);
523*1c60b9acSAndroid Build Coastguard Worker 
524*1c60b9acSAndroid Build Coastguard Worker 	/*
525*1c60b9acSAndroid Build Coastguard Worker 	 * Bind the child's stdin / out / err to its side of our pipes
526*1c60b9acSAndroid Build Coastguard Worker 	 */
527*1c60b9acSAndroid Build Coastguard Worker 
528*1c60b9acSAndroid Build Coastguard Worker 	for (m = 0; m < 3; m++) {
529*1c60b9acSAndroid Build Coastguard Worker 		if (dup2(lsp->pipe_fds[m][m != 0], m) < 0) {
530*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: stdin dup2 failed\n", __func__);
531*1c60b9acSAndroid Build Coastguard Worker 			goto bail3;
532*1c60b9acSAndroid Build Coastguard Worker 		}
533*1c60b9acSAndroid Build Coastguard Worker 		/*
534*1c60b9acSAndroid Build Coastguard Worker 		 * CLOEXEC on the lws-side of the pipe fds should have already
535*1c60b9acSAndroid Build Coastguard Worker 		 * dealt with closing those for the child perspective.
536*1c60b9acSAndroid Build Coastguard Worker 		 *
537*1c60b9acSAndroid Build Coastguard Worker 		 * Now it has done the dup, the child should close its original
538*1c60b9acSAndroid Build Coastguard Worker 		 * copies of its side of the pipes.
539*1c60b9acSAndroid Build Coastguard Worker 		 */
540*1c60b9acSAndroid Build Coastguard Worker 
541*1c60b9acSAndroid Build Coastguard Worker 		close(lsp->pipe_fds[m][m != 0]);
542*1c60b9acSAndroid Build Coastguard Worker 	}
543*1c60b9acSAndroid Build Coastguard Worker 
544*1c60b9acSAndroid Build Coastguard Worker #if defined(__sun) || !defined(LWS_HAVE_VFORK) || !defined(LWS_HAVE_EXECVPE)
545*1c60b9acSAndroid Build Coastguard Worker #if defined(__linux__) || defined(__APPLE__) || defined(__sun)
546*1c60b9acSAndroid Build Coastguard Worker 	m = 0;
547*1c60b9acSAndroid Build Coastguard Worker 	while (i->env_array[m]){
548*1c60b9acSAndroid Build Coastguard Worker 		const char *p = strchr(i->env_array[m], '=');
549*1c60b9acSAndroid Build Coastguard Worker 		int naml = lws_ptr_diff(p, i->env_array[m]);
550*1c60b9acSAndroid Build Coastguard Worker 		char enam[32];
551*1c60b9acSAndroid Build Coastguard Worker 
552*1c60b9acSAndroid Build Coastguard Worker 		lws_strnncpy(enam, i->env_array[m], naml, sizeof(enam));
553*1c60b9acSAndroid Build Coastguard Worker 		setenv(enam, p, 1);
554*1c60b9acSAndroid Build Coastguard Worker 		m++;
555*1c60b9acSAndroid Build Coastguard Worker 	}
556*1c60b9acSAndroid Build Coastguard Worker #endif
557*1c60b9acSAndroid Build Coastguard Worker 	execvp(i->exec_array[0], (char * const *)&i->exec_array[0]);
558*1c60b9acSAndroid Build Coastguard Worker #else
559*1c60b9acSAndroid Build Coastguard Worker 	execvpe(i->exec_array[0], (char * const *)&i->exec_array[0],
560*1c60b9acSAndroid Build Coastguard Worker 		(char **)&i->env_array[0]);
561*1c60b9acSAndroid Build Coastguard Worker #endif
562*1c60b9acSAndroid Build Coastguard Worker 
563*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: child exec of %s failed %d\n", __func__, i->exec_array[0],
564*1c60b9acSAndroid Build Coastguard Worker 		 LWS_ERRNO);
565*1c60b9acSAndroid Build Coastguard Worker 
566*1c60b9acSAndroid Build Coastguard Worker 	_exit(1);
567*1c60b9acSAndroid Build Coastguard Worker 
568*1c60b9acSAndroid Build Coastguard Worker bail3:
569*1c60b9acSAndroid Build Coastguard Worker 
570*1c60b9acSAndroid Build Coastguard Worker 	while (--n >= 0)
571*1c60b9acSAndroid Build Coastguard Worker 		__remove_wsi_socket_from_fds(lsp->stdwsi[n]);
572*1c60b9acSAndroid Build Coastguard Worker bail2:
573*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++)
574*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->stdwsi[n])
575*1c60b9acSAndroid Build Coastguard Worker 			__lws_free_wsi(lsp->stdwsi[n]);
576*1c60b9acSAndroid Build Coastguard Worker 
577*1c60b9acSAndroid Build Coastguard Worker bail1:
578*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
579*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->pipe_fds[n][0] >= 0)
580*1c60b9acSAndroid Build Coastguard Worker 			close(lsp->pipe_fds[n][0]);
581*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->pipe_fds[n][1] >= 0)
582*1c60b9acSAndroid Build Coastguard Worker 			close(lsp->pipe_fds[n][1]);
583*1c60b9acSAndroid Build Coastguard Worker 	}
584*1c60b9acSAndroid Build Coastguard Worker 
585*1c60b9acSAndroid Build Coastguard Worker 	lws_free(lsp);
586*1c60b9acSAndroid Build Coastguard Worker 
587*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: failed\n", __func__);
588*1c60b9acSAndroid Build Coastguard Worker 
589*1c60b9acSAndroid Build Coastguard Worker 	return NULL;
590*1c60b9acSAndroid Build Coastguard Worker }
591*1c60b9acSAndroid Build Coastguard Worker 
592*1c60b9acSAndroid Build Coastguard Worker void
lws_spawn_stdwsi_closed(struct lws_spawn_piped * lsp,struct lws * wsi)593*1c60b9acSAndroid Build Coastguard Worker lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi)
594*1c60b9acSAndroid Build Coastguard Worker {
595*1c60b9acSAndroid Build Coastguard Worker 	int n;
596*1c60b9acSAndroid Build Coastguard Worker 
597*1c60b9acSAndroid Build Coastguard Worker 	assert(lsp);
598*1c60b9acSAndroid Build Coastguard Worker 	lsp->pipes_alive--;
599*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive);
600*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->pipes_alive)
601*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
602*1c60b9acSAndroid Build Coastguard Worker 				 &lsp->sul_reap, lws_spawn_sul_reap, 1);
603*1c60b9acSAndroid Build Coastguard Worker 
604*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++)
605*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->stdwsi[n] == wsi)
606*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[n] = NULL;
607*1c60b9acSAndroid Build Coastguard Worker }
608*1c60b9acSAndroid Build Coastguard Worker 
609*1c60b9acSAndroid Build Coastguard Worker int
lws_spawn_get_stdfd(struct lws * wsi)610*1c60b9acSAndroid Build Coastguard Worker lws_spawn_get_stdfd(struct lws *wsi)
611*1c60b9acSAndroid Build Coastguard Worker {
612*1c60b9acSAndroid Build Coastguard Worker 	return wsi->lsp_channel;
613*1c60b9acSAndroid Build Coastguard Worker }
614