xref: /aosp_15_r20/external/libwebsockets/lib/plat/windows/windows-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 #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker 
27*1c60b9acSAndroid Build Coastguard Worker #include <tchar.h>
28*1c60b9acSAndroid Build Coastguard Worker #include <stdio.h>
29*1c60b9acSAndroid Build Coastguard Worker #include <strsafe.h>
30*1c60b9acSAndroid Build Coastguard Worker 
31*1c60b9acSAndroid Build Coastguard Worker void
lws_spawn_timeout(struct lws_sorted_usec_list * sul)32*1c60b9acSAndroid Build Coastguard Worker lws_spawn_timeout(struct lws_sorted_usec_list *sul)
33*1c60b9acSAndroid Build Coastguard Worker {
34*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped *lsp = lws_container_of(sul,
35*1c60b9acSAndroid Build Coastguard Worker 					struct lws_spawn_piped, sul);
36*1c60b9acSAndroid Build Coastguard Worker 
37*1c60b9acSAndroid Build Coastguard Worker 	lwsl_warn("%s: spawn exceeded timeout, killing\n", __func__);
38*1c60b9acSAndroid Build Coastguard Worker 
39*1c60b9acSAndroid Build Coastguard Worker 	lws_spawn_piped_kill_child_process(lsp);
40*1c60b9acSAndroid Build Coastguard Worker }
41*1c60b9acSAndroid Build Coastguard Worker 
42*1c60b9acSAndroid Build Coastguard Worker void
lws_spawn_sul_reap(struct lws_sorted_usec_list * sul)43*1c60b9acSAndroid Build Coastguard Worker lws_spawn_sul_reap(struct lws_sorted_usec_list *sul)
44*1c60b9acSAndroid Build Coastguard Worker {
45*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped *lsp = lws_container_of(sul,
46*1c60b9acSAndroid Build Coastguard Worker 					struct lws_spawn_piped, sul_reap);
47*1c60b9acSAndroid Build Coastguard Worker 
48*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: reaping spawn after last stdpipe, tries left %d\n",
49*1c60b9acSAndroid Build Coastguard Worker 		    __func__, lsp->reap_retry_budget);
50*1c60b9acSAndroid Build Coastguard Worker 	if (!lws_spawn_reap(lsp) && !lsp->pipes_alive) {
51*1c60b9acSAndroid Build Coastguard Worker 		if (--lsp->reap_retry_budget) {
52*1c60b9acSAndroid Build Coastguard Worker 			lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
53*1c60b9acSAndroid Build Coastguard Worker 					 &lsp->sul_reap, lws_spawn_sul_reap,
54*1c60b9acSAndroid Build Coastguard Worker 					 250 * LWS_US_PER_MS);
55*1c60b9acSAndroid Build Coastguard Worker 		} else {
56*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: Unable to reap lsp %p, killing\n",
57*1c60b9acSAndroid Build Coastguard Worker 				 __func__, lsp);
58*1c60b9acSAndroid Build Coastguard Worker 			lsp->reap_retry_budget = 20;
59*1c60b9acSAndroid Build Coastguard Worker 			lws_spawn_piped_kill_child_process(lsp);
60*1c60b9acSAndroid Build Coastguard Worker 		}
61*1c60b9acSAndroid Build Coastguard Worker 	}
62*1c60b9acSAndroid Build Coastguard Worker }
63*1c60b9acSAndroid Build Coastguard Worker 
64*1c60b9acSAndroid Build Coastguard Worker static struct lws *
lws_create_basic_wsi(struct lws_context * context,int tsi,const struct lws_role_ops * ops)65*1c60b9acSAndroid Build Coastguard Worker lws_create_basic_wsi(struct lws_context *context, int tsi,
66*1c60b9acSAndroid Build Coastguard Worker 		     const struct lws_role_ops *ops)
67*1c60b9acSAndroid Build Coastguard Worker {
68*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context_per_thread *pt = &context->pt[tsi];
69*1c60b9acSAndroid Build Coastguard Worker 	struct lws *new_wsi;
70*1c60b9acSAndroid Build Coastguard Worker 
71*1c60b9acSAndroid Build Coastguard Worker 	if (!context->vhost_list)
72*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
73*1c60b9acSAndroid Build Coastguard Worker 
74*1c60b9acSAndroid Build Coastguard Worker 	if ((unsigned int)context->pt[tsi].fds_count ==
75*1c60b9acSAndroid Build Coastguard Worker 	    context->fd_limit_per_thread - 1) {
76*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("no space for new conn\n");
77*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
78*1c60b9acSAndroid Build Coastguard Worker 	}
79*1c60b9acSAndroid Build Coastguard Worker 
80*1c60b9acSAndroid Build Coastguard Worker 	lws_context_lock(context, __func__);
81*1c60b9acSAndroid Build Coastguard Worker 	new_wsi = __lws_wsi_create_with_role(context, tsi, ops, NULL);
82*1c60b9acSAndroid Build Coastguard Worker 	lws_context_unlock(context);
83*1c60b9acSAndroid Build Coastguard Worker 	if (new_wsi == NULL) {
84*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("Out of memory for new connection\n");
85*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
86*1c60b9acSAndroid Build Coastguard Worker 	}
87*1c60b9acSAndroid Build Coastguard Worker 
88*1c60b9acSAndroid Build Coastguard Worker 	new_wsi->rxflow_change_to = LWS_RXFLOW_ALLOW;
89*1c60b9acSAndroid Build Coastguard Worker 
90*1c60b9acSAndroid Build Coastguard Worker 	/* initialize the instance struct */
91*1c60b9acSAndroid Build Coastguard Worker 
92*1c60b9acSAndroid Build Coastguard Worker 	lws_role_transition(new_wsi, 0, LRS_ESTABLISHED, ops);
93*1c60b9acSAndroid Build Coastguard Worker 
94*1c60b9acSAndroid Build Coastguard Worker 	new_wsi->hdr_parsing_completed = 0;
95*1c60b9acSAndroid Build Coastguard Worker 	new_wsi->position_in_fds_table = LWS_NO_FDS_POS;
96*1c60b9acSAndroid Build Coastguard Worker 
97*1c60b9acSAndroid Build Coastguard Worker 	/*
98*1c60b9acSAndroid Build Coastguard Worker 	 * these can only be set once the protocol is known
99*1c60b9acSAndroid Build Coastguard Worker 	 * we set an unestablished connection's protocol pointer
100*1c60b9acSAndroid Build Coastguard Worker 	 * to the start of the defauly vhost supported list, so it can look
101*1c60b9acSAndroid Build Coastguard Worker 	 * for matching ones during the handshake
102*1c60b9acSAndroid Build Coastguard Worker 	 */
103*1c60b9acSAndroid Build Coastguard Worker 
104*1c60b9acSAndroid Build Coastguard Worker 	new_wsi->user_space = NULL;
105*1c60b9acSAndroid Build Coastguard Worker 	new_wsi->desc.sockfd = LWS_SOCK_INVALID;
106*1c60b9acSAndroid Build Coastguard Worker 
107*1c60b9acSAndroid Build Coastguard Worker 	return new_wsi;
108*1c60b9acSAndroid Build Coastguard Worker }
109*1c60b9acSAndroid Build Coastguard Worker 
110*1c60b9acSAndroid Build Coastguard Worker void
lws_spawn_piped_destroy(struct lws_spawn_piped ** _lsp)111*1c60b9acSAndroid Build Coastguard Worker lws_spawn_piped_destroy(struct lws_spawn_piped **_lsp)
112*1c60b9acSAndroid Build Coastguard Worker {
113*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped *lsp = *_lsp;
114*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi;
115*1c60b9acSAndroid Build Coastguard Worker 	int n;
116*1c60b9acSAndroid Build Coastguard Worker 
117*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp)
118*1c60b9acSAndroid Build Coastguard Worker 		return;
119*1c60b9acSAndroid Build Coastguard Worker 
120*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
121*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->pipe_fds[n][!!(n == 0)]) {
122*1c60b9acSAndroid Build Coastguard Worker 			CloseHandle(lsp->pipe_fds[n][n == 0]);
123*1c60b9acSAndroid Build Coastguard Worker 			lsp->pipe_fds[n][n == 0] = NULL;
124*1c60b9acSAndroid Build Coastguard Worker 		}
125*1c60b9acSAndroid Build Coastguard Worker 
126*1c60b9acSAndroid Build Coastguard Worker 		for (n = 0; n < 3; n++) {
127*1c60b9acSAndroid Build Coastguard Worker 			if (lsp->stdwsi[n]) {
128*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: closing stdwsi %d\n", __func__, n);
129*1c60b9acSAndroid Build Coastguard Worker 				wsi = lsp->stdwsi[n];
130*1c60b9acSAndroid Build Coastguard Worker 				lsp->stdwsi[n]->desc.filefd = NULL;
131*1c60b9acSAndroid Build Coastguard Worker 				lsp->stdwsi[n] = NULL;
132*1c60b9acSAndroid Build Coastguard Worker 				lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC);
133*1c60b9acSAndroid Build Coastguard Worker 			}
134*1c60b9acSAndroid Build Coastguard Worker 		}
135*1c60b9acSAndroid Build Coastguard Worker 	}
136*1c60b9acSAndroid Build Coastguard Worker 
137*1c60b9acSAndroid Build Coastguard Worker 	lws_dll2_remove(&lsp->dll);
138*1c60b9acSAndroid Build Coastguard Worker 
139*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_cancel(&lsp->sul);
140*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_cancel(&lsp->sul_reap);
141*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_cancel(&lsp->sul_poll);
142*1c60b9acSAndroid Build Coastguard Worker 
143*1c60b9acSAndroid Build Coastguard Worker 	lwsl_warn("%s: deleting lsp\n", __func__);
144*1c60b9acSAndroid Build Coastguard Worker 
145*1c60b9acSAndroid Build Coastguard Worker 	lws_free_set_NULL((*_lsp));
146*1c60b9acSAndroid Build Coastguard Worker }
147*1c60b9acSAndroid Build Coastguard Worker 
148*1c60b9acSAndroid Build Coastguard Worker int
lws_spawn_reap(struct lws_spawn_piped * lsp)149*1c60b9acSAndroid Build Coastguard Worker lws_spawn_reap(struct lws_spawn_piped *lsp)
150*1c60b9acSAndroid Build Coastguard Worker {
151*1c60b9acSAndroid Build Coastguard Worker 
152*1c60b9acSAndroid Build Coastguard Worker 	void *opaque = lsp->info.opaque;
153*1c60b9acSAndroid Build Coastguard Worker 	lsp_cb_t cb = lsp->info.reap_cb;
154*1c60b9acSAndroid Build Coastguard Worker 	struct _lws_siginfo_t lsi;
155*1c60b9acSAndroid Build Coastguard Worker 	lws_usec_t acct[4];
156*1c60b9acSAndroid Build Coastguard Worker 	DWORD ex;
157*1c60b9acSAndroid Build Coastguard Worker 
158*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->child_pid)
159*1c60b9acSAndroid Build Coastguard Worker 		return 0;
160*1c60b9acSAndroid Build Coastguard Worker 
161*1c60b9acSAndroid Build Coastguard Worker 	if (!GetExitCodeProcess(lsp->child_pid, &ex)) {
162*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: GetExitCodeProcess failed\n", __func__);
163*1c60b9acSAndroid Build Coastguard Worker 		return 0;
164*1c60b9acSAndroid Build Coastguard Worker 	}
165*1c60b9acSAndroid Build Coastguard Worker 
166*1c60b9acSAndroid Build Coastguard Worker 	/* nonzero = success */
167*1c60b9acSAndroid Build Coastguard Worker 
168*1c60b9acSAndroid Build Coastguard Worker 	if (ex == STILL_ACTIVE) {
169*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: still active\n", __func__);
170*1c60b9acSAndroid Build Coastguard Worker 		return 0;
171*1c60b9acSAndroid Build Coastguard Worker 	}
172*1c60b9acSAndroid Build Coastguard Worker 
173*1c60b9acSAndroid Build Coastguard Worker 	/* mark the earliest time we knew he had gone */
174*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->reaped) {
175*1c60b9acSAndroid Build Coastguard Worker 		lsp->reaped = lws_now_usecs();
176*1c60b9acSAndroid Build Coastguard Worker 
177*1c60b9acSAndroid Build Coastguard Worker 		/*
178*1c60b9acSAndroid Build Coastguard Worker 		 * Switch the timeout to restrict the amount of grace time
179*1c60b9acSAndroid Build Coastguard Worker 		 * to drain stdwsi
180*1c60b9acSAndroid Build Coastguard Worker 		 */
181*1c60b9acSAndroid Build Coastguard Worker 
182*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
183*1c60b9acSAndroid Build Coastguard Worker 				 &lsp->sul, lws_spawn_timeout,
184*1c60b9acSAndroid Build Coastguard Worker 				 5 * LWS_US_PER_SEC);
185*1c60b9acSAndroid Build Coastguard Worker 	}
186*1c60b9acSAndroid Build Coastguard Worker 
187*1c60b9acSAndroid Build Coastguard Worker 	/*
188*1c60b9acSAndroid Build Coastguard Worker 	 * Stage finalizing our reaction to the process going down until the
189*1c60b9acSAndroid Build Coastguard Worker 	 * stdwsi flushed whatever is in flight and all noticed they were
190*1c60b9acSAndroid Build Coastguard Worker 	 * closed.  For that reason, each stdwsi close must call lws_spawn_reap
191*1c60b9acSAndroid Build Coastguard Worker 	 * to check if that was the last one and we can proceed with the reap.
192*1c60b9acSAndroid Build Coastguard Worker 	 */
193*1c60b9acSAndroid Build Coastguard Worker 
194*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->ungraceful && lsp->pipes_alive) {
195*1c60b9acSAndroid Build Coastguard Worker 		lwsl_notice("%s: stdwsi alive, not reaping\n", __func__);
196*1c60b9acSAndroid Build Coastguard Worker 		return 0;
197*1c60b9acSAndroid Build Coastguard Worker 	}
198*1c60b9acSAndroid Build Coastguard Worker 
199*1c60b9acSAndroid Build Coastguard Worker 	/* we reached the reap point, no need for timeout wait */
200*1c60b9acSAndroid Build Coastguard Worker 
201*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_cancel(&lsp->sul);
202*1c60b9acSAndroid Build Coastguard Worker 
203*1c60b9acSAndroid Build Coastguard Worker 	/*
204*1c60b9acSAndroid Build Coastguard Worker 	 * All the stdwsi went down, nothing more is coming... it's over
205*1c60b9acSAndroid Build Coastguard Worker 	 * Collect the final information and then reap the dead process
206*1c60b9acSAndroid Build Coastguard Worker 	 */
207*1c60b9acSAndroid Build Coastguard Worker 
208*1c60b9acSAndroid Build Coastguard Worker 	lsi.retcode = 0x10000 | (int)ex;
209*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: process exit 0x%x\n", __func__, lsi.retcode);
210*1c60b9acSAndroid Build Coastguard Worker 	lsp->child_pid = NULL;
211*1c60b9acSAndroid Build Coastguard Worker 
212*1c60b9acSAndroid Build Coastguard Worker 	/* destroy the lsp itself first (it's freed and plsp set NULL */
213*1c60b9acSAndroid Build Coastguard Worker 
214*1c60b9acSAndroid Build Coastguard Worker 	if (lsp->info.plsp)
215*1c60b9acSAndroid Build Coastguard Worker 		lws_spawn_piped_destroy(lsp->info.plsp);
216*1c60b9acSAndroid Build Coastguard Worker 
217*1c60b9acSAndroid Build Coastguard Worker 	/* then do the parent callback informing it's destroyed */
218*1c60b9acSAndroid Build Coastguard Worker 
219*1c60b9acSAndroid Build Coastguard Worker 	memset(acct, 0, sizeof(acct));
220*1c60b9acSAndroid Build Coastguard Worker 	if (cb)
221*1c60b9acSAndroid Build Coastguard Worker 		cb(opaque, acct, &lsi, 0);
222*1c60b9acSAndroid Build Coastguard Worker 
223*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: completed reap\n", __func__);
224*1c60b9acSAndroid Build Coastguard Worker 
225*1c60b9acSAndroid Build Coastguard Worker 	return 1; /* was reaped */
226*1c60b9acSAndroid Build Coastguard Worker }
227*1c60b9acSAndroid Build Coastguard Worker 
228*1c60b9acSAndroid Build Coastguard Worker int
lws_spawn_piped_kill_child_process(struct lws_spawn_piped * lsp)229*1c60b9acSAndroid Build Coastguard Worker lws_spawn_piped_kill_child_process(struct lws_spawn_piped *lsp)
230*1c60b9acSAndroid Build Coastguard Worker {
231*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->child_pid)
232*1c60b9acSAndroid Build Coastguard Worker 		return 1;
233*1c60b9acSAndroid Build Coastguard Worker 
234*1c60b9acSAndroid Build Coastguard Worker 	lsp->ungraceful = 1; /* don't wait for flushing, just kill it */
235*1c60b9acSAndroid Build Coastguard Worker 
236*1c60b9acSAndroid Build Coastguard Worker 	if (lws_spawn_reap(lsp))
237*1c60b9acSAndroid Build Coastguard Worker 		/* that may have invalidated lsp */
238*1c60b9acSAndroid Build Coastguard Worker 		return 0;
239*1c60b9acSAndroid Build Coastguard Worker 
240*1c60b9acSAndroid Build Coastguard Worker 	lwsl_warn("%s: calling TerminateProcess on child pid\n", __func__);
241*1c60b9acSAndroid Build Coastguard Worker 	TerminateProcess(lsp->child_pid, 252);
242*1c60b9acSAndroid Build Coastguard Worker 	lws_spawn_reap(lsp);
243*1c60b9acSAndroid Build Coastguard Worker 
244*1c60b9acSAndroid Build Coastguard Worker 	/* that may have invalidated lsp */
245*1c60b9acSAndroid Build Coastguard Worker 
246*1c60b9acSAndroid Build Coastguard Worker 	return 0;
247*1c60b9acSAndroid Build Coastguard Worker }
248*1c60b9acSAndroid Build Coastguard Worker 
249*1c60b9acSAndroid Build Coastguard Worker static void
windows_pipe_poll_hack(lws_sorted_usec_list_t * sul)250*1c60b9acSAndroid Build Coastguard Worker windows_pipe_poll_hack(lws_sorted_usec_list_t *sul)
251*1c60b9acSAndroid Build Coastguard Worker {
252*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped *lsp = lws_container_of(sul,
253*1c60b9acSAndroid Build Coastguard Worker 					struct lws_spawn_piped, sul_poll);
254*1c60b9acSAndroid Build Coastguard Worker 	struct lws *wsi, *wsi1;
255*1c60b9acSAndroid Build Coastguard Worker 	DWORD br;
256*1c60b9acSAndroid Build Coastguard Worker 	char c;
257*1c60b9acSAndroid Build Coastguard Worker 
258*1c60b9acSAndroid Build Coastguard Worker 	/*
259*1c60b9acSAndroid Build Coastguard Worker 	 * Do it first, we know lsp exists and if it's destroyed inbetweentimes,
260*1c60b9acSAndroid Build Coastguard Worker 	 * it will already have cancelled this
261*1c60b9acSAndroid Build Coastguard Worker 	 */
262*1c60b9acSAndroid Build Coastguard Worker 
263*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_schedule(lsp->context, 0, &lsp->sul_poll,
264*1c60b9acSAndroid Build Coastguard Worker 			 windows_pipe_poll_hack, 50 * LWS_US_PER_MS);
265*1c60b9acSAndroid Build Coastguard Worker 
266*1c60b9acSAndroid Build Coastguard Worker 	wsi = lsp->stdwsi[LWS_STDOUT];
267*1c60b9acSAndroid Build Coastguard Worker 	wsi1 = lsp->stdwsi[LWS_STDERR];
268*1c60b9acSAndroid Build Coastguard Worker 	if (wsi && lsp->pipe_fds[LWS_STDOUT][0] != NULL) {
269*1c60b9acSAndroid Build Coastguard Worker 		if (!PeekNamedPipe(lsp->pipe_fds[LWS_STDOUT][0], &c, 1, &br,
270*1c60b9acSAndroid Build Coastguard Worker 				   NULL, NULL)) {
271*1c60b9acSAndroid Build Coastguard Worker 
272*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: stdout pipe errored\n", __func__);
273*1c60b9acSAndroid Build Coastguard Worker 			CloseHandle(lsp->stdwsi[LWS_STDOUT]->desc.filefd);
274*1c60b9acSAndroid Build Coastguard Worker 			lsp->pipe_fds[LWS_STDOUT][0] = NULL;
275*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[LWS_STDOUT]->desc.filefd = NULL;
276*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[LWS_STDOUT] = NULL;
277*1c60b9acSAndroid Build Coastguard Worker 			lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC);
278*1c60b9acSAndroid Build Coastguard Worker 
279*1c60b9acSAndroid Build Coastguard Worker 			if (lsp->stdwsi[LWS_STDIN]) {
280*1c60b9acSAndroid Build Coastguard Worker 				lwsl_notice("%s: closing stdin from stdout close\n",
281*1c60b9acSAndroid Build Coastguard Worker 						__func__);
282*1c60b9acSAndroid Build Coastguard Worker 				CloseHandle(lsp->stdwsi[LWS_STDIN]->desc.filefd);
283*1c60b9acSAndroid Build Coastguard Worker 				wsi = lsp->stdwsi[LWS_STDIN];
284*1c60b9acSAndroid Build Coastguard Worker 				lsp->stdwsi[LWS_STDIN]->desc.filefd = NULL;
285*1c60b9acSAndroid Build Coastguard Worker 				lsp->stdwsi[LWS_STDIN] = NULL;
286*1c60b9acSAndroid Build Coastguard Worker 				lsp->pipe_fds[LWS_STDIN][1] = NULL;
287*1c60b9acSAndroid Build Coastguard Worker 				lws_set_timeout(wsi, 1, LWS_TO_KILL_SYNC);
288*1c60b9acSAndroid Build Coastguard Worker 			}
289*1c60b9acSAndroid Build Coastguard Worker 
290*1c60b9acSAndroid Build Coastguard Worker 			/*
291*1c60b9acSAndroid Build Coastguard Worker 			 * lsp may be destroyed by here... if we wanted to
292*1c60b9acSAndroid Build Coastguard Worker 			 * handle a still-extant stderr we'll get it next time
293*1c60b9acSAndroid Build Coastguard Worker 			 */
294*1c60b9acSAndroid Build Coastguard Worker 
295*1c60b9acSAndroid Build Coastguard Worker 			return;
296*1c60b9acSAndroid Build Coastguard Worker 		} else
297*1c60b9acSAndroid Build Coastguard Worker 			if (br)
298*1c60b9acSAndroid Build Coastguard Worker 				wsi->a.protocol->callback(wsi,
299*1c60b9acSAndroid Build Coastguard Worker 							LWS_CALLBACK_RAW_RX_FILE,
300*1c60b9acSAndroid Build Coastguard Worker 							NULL, NULL, 0);
301*1c60b9acSAndroid Build Coastguard Worker 	}
302*1c60b9acSAndroid Build Coastguard Worker 
303*1c60b9acSAndroid Build Coastguard Worker 	/*
304*1c60b9acSAndroid Build Coastguard Worker 	 * lsp may have been destroyed above
305*1c60b9acSAndroid Build Coastguard Worker 	 */
306*1c60b9acSAndroid Build Coastguard Worker 
307*1c60b9acSAndroid Build Coastguard Worker 	if (wsi1 && lsp->pipe_fds[LWS_STDERR][0]) {
308*1c60b9acSAndroid Build Coastguard Worker 		if (!PeekNamedPipe(lsp->pipe_fds[LWS_STDERR][0], &c, 1, &br,
309*1c60b9acSAndroid Build Coastguard Worker 				   NULL, NULL)) {
310*1c60b9acSAndroid Build Coastguard Worker 
311*1c60b9acSAndroid Build Coastguard Worker 			lwsl_notice("%s: stderr pipe errored\n", __func__);
312*1c60b9acSAndroid Build Coastguard Worker 			CloseHandle(wsi1->desc.filefd);
313*1c60b9acSAndroid Build Coastguard Worker 			/*
314*1c60b9acSAndroid Build Coastguard Worker 			 * Assume is stderr still extant on entry, lsp can't
315*1c60b9acSAndroid Build Coastguard Worker 			 * have been destroyed by stdout/stdin processing
316*1c60b9acSAndroid Build Coastguard Worker 			 */
317*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[LWS_STDERR]->desc.filefd = NULL;
318*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[LWS_STDERR] = NULL;
319*1c60b9acSAndroid Build Coastguard Worker 			lsp->pipe_fds[LWS_STDERR][0] = NULL;
320*1c60b9acSAndroid Build Coastguard Worker 			lws_set_timeout(wsi1, 1, LWS_TO_KILL_SYNC);
321*1c60b9acSAndroid Build Coastguard Worker 			/*
322*1c60b9acSAndroid Build Coastguard Worker 			 * lsp may have been destroyed above
323*1c60b9acSAndroid Build Coastguard Worker 			 */
324*1c60b9acSAndroid Build Coastguard Worker 		} else
325*1c60b9acSAndroid Build Coastguard Worker 			if (br)
326*1c60b9acSAndroid Build Coastguard Worker 				wsi1->a.protocol->callback(wsi1,
327*1c60b9acSAndroid Build Coastguard Worker 							LWS_CALLBACK_RAW_RX_FILE,
328*1c60b9acSAndroid Build Coastguard Worker 							NULL, NULL, 0);
329*1c60b9acSAndroid Build Coastguard Worker 	}
330*1c60b9acSAndroid Build Coastguard Worker }
331*1c60b9acSAndroid Build Coastguard Worker 
332*1c60b9acSAndroid Build Coastguard Worker 
333*1c60b9acSAndroid Build Coastguard Worker 
334*1c60b9acSAndroid Build Coastguard Worker /*
335*1c60b9acSAndroid Build Coastguard Worker  * Deals with spawning a subprocess and executing it securely with stdin/out/err
336*1c60b9acSAndroid Build Coastguard Worker  * diverted into pipes
337*1c60b9acSAndroid Build Coastguard Worker  */
338*1c60b9acSAndroid Build Coastguard Worker 
339*1c60b9acSAndroid Build Coastguard Worker struct lws_spawn_piped *
lws_spawn_piped(const struct lws_spawn_piped_info * i)340*1c60b9acSAndroid Build Coastguard Worker lws_spawn_piped(const struct lws_spawn_piped_info *i)
341*1c60b9acSAndroid Build Coastguard Worker {
342*1c60b9acSAndroid Build Coastguard Worker 	const struct lws_protocols *pcol = i->vh->context->vhost_list->protocols;
343*1c60b9acSAndroid Build Coastguard Worker 	struct lws_context *context = i->vh->context;
344*1c60b9acSAndroid Build Coastguard Worker 	struct lws_spawn_piped *lsp;
345*1c60b9acSAndroid Build Coastguard Worker 	PROCESS_INFORMATION pi;
346*1c60b9acSAndroid Build Coastguard Worker 	SECURITY_ATTRIBUTES sa;
347*1c60b9acSAndroid Build Coastguard Worker 	char cli[300], *p;
348*1c60b9acSAndroid Build Coastguard Worker 	STARTUPINFO si;
349*1c60b9acSAndroid Build Coastguard Worker 	int n;
350*1c60b9acSAndroid Build Coastguard Worker 
351*1c60b9acSAndroid Build Coastguard Worker 	if (i->protocol_name)
352*1c60b9acSAndroid Build Coastguard Worker 		pcol = lws_vhost_name_to_protocol(i->vh, i->protocol_name);
353*1c60b9acSAndroid Build Coastguard Worker 	if (!pcol) {
354*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: unknown protocol %s\n", __func__,
355*1c60b9acSAndroid Build Coastguard Worker 			 i->protocol_name ? i->protocol_name : "default");
356*1c60b9acSAndroid Build Coastguard Worker 
357*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
358*1c60b9acSAndroid Build Coastguard Worker 	}
359*1c60b9acSAndroid Build Coastguard Worker 
360*1c60b9acSAndroid Build Coastguard Worker 	lsp = lws_zalloc(sizeof(*lsp), __func__);
361*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp) {
362*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: OOM\n", __func__);
363*1c60b9acSAndroid Build Coastguard Worker 		return NULL;
364*1c60b9acSAndroid Build Coastguard Worker 	}
365*1c60b9acSAndroid Build Coastguard Worker 
366*1c60b9acSAndroid Build Coastguard Worker 	/* wholesale take a copy of info */
367*1c60b9acSAndroid Build Coastguard Worker 	lsp->info = *i;
368*1c60b9acSAndroid Build Coastguard Worker 	lsp->context = context;
369*1c60b9acSAndroid Build Coastguard Worker 	lsp->reap_retry_budget = 20;
370*1c60b9acSAndroid Build Coastguard Worker 
371*1c60b9acSAndroid Build Coastguard Worker 	/*
372*1c60b9acSAndroid Build Coastguard Worker 	 * Prepare the stdin / out / err pipes
373*1c60b9acSAndroid Build Coastguard Worker 	 */
374*1c60b9acSAndroid Build Coastguard Worker 
375*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
376*1c60b9acSAndroid Build Coastguard Worker 		lsp->pipe_fds[n][0] = NULL;
377*1c60b9acSAndroid Build Coastguard Worker 		lsp->pipe_fds[n][1] = NULL;
378*1c60b9acSAndroid Build Coastguard Worker 	}
379*1c60b9acSAndroid Build Coastguard Worker 
380*1c60b9acSAndroid Build Coastguard Worker 	/* create pipes for [stdin|stdout] and [stderr] */
381*1c60b9acSAndroid Build Coastguard Worker 
382*1c60b9acSAndroid Build Coastguard Worker 	memset(&sa, 0, sizeof(sa));
383*1c60b9acSAndroid Build Coastguard Worker 	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
384*1c60b9acSAndroid Build Coastguard Worker 	sa.bInheritHandle = TRUE; /* inherit the pipes */
385*1c60b9acSAndroid Build Coastguard Worker 	sa.lpSecurityDescriptor = NULL;
386*1c60b9acSAndroid Build Coastguard Worker 
387*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
388*1c60b9acSAndroid Build Coastguard Worker 		DWORD waitmode = PIPE_NOWAIT;
389*1c60b9acSAndroid Build Coastguard Worker 
390*1c60b9acSAndroid Build Coastguard Worker 		if (!CreatePipe(&lsp->pipe_fds[n][0], &lsp->pipe_fds[n][1],
391*1c60b9acSAndroid Build Coastguard Worker 				&sa, 0)) {
392*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: CreatePipe() failed\n", __func__);
393*1c60b9acSAndroid Build Coastguard Worker 			goto bail1;
394*1c60b9acSAndroid Build Coastguard Worker 		}
395*1c60b9acSAndroid Build Coastguard Worker 
396*1c60b9acSAndroid Build Coastguard Worker 		SetNamedPipeHandleState(lsp->pipe_fds[1][0], &waitmode, NULL, NULL);
397*1c60b9acSAndroid Build Coastguard Worker 		SetNamedPipeHandleState(lsp->pipe_fds[2][0], &waitmode, NULL, NULL);
398*1c60b9acSAndroid Build Coastguard Worker 
399*1c60b9acSAndroid Build Coastguard Worker 		/* don't inherit the pipe side that belongs to the parent */
400*1c60b9acSAndroid Build Coastguard Worker 
401*1c60b9acSAndroid Build Coastguard Worker 		if (!SetHandleInformation(&lsp->pipe_fds[n][!n],
402*1c60b9acSAndroid Build Coastguard Worker 					  HANDLE_FLAG_INHERIT, 0)) {
403*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: SetHandleInformation() failed\n", __func__);
404*1c60b9acSAndroid Build Coastguard Worker 			//goto bail1;
405*1c60b9acSAndroid Build Coastguard Worker 		}
406*1c60b9acSAndroid Build Coastguard Worker 	}
407*1c60b9acSAndroid Build Coastguard Worker 
408*1c60b9acSAndroid Build Coastguard Worker 	/* create wsis for each stdin/out/err fd */
409*1c60b9acSAndroid Build Coastguard Worker 
410*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
411*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n] = lws_create_basic_wsi(i->vh->context, i->tsi,
412*1c60b9acSAndroid Build Coastguard Worker 					  i->ops ? i->ops : &role_ops_raw_file);
413*1c60b9acSAndroid Build Coastguard Worker 		if (!lsp->stdwsi[n]) {
414*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: unable to create lsp stdwsi\n", __func__);
415*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
416*1c60b9acSAndroid Build Coastguard Worker 		}
417*1c60b9acSAndroid Build Coastguard Worker 
418*1c60b9acSAndroid Build Coastguard Worker                 __lws_lc_tag(i->vh->context, &i->vh->context->lcg[LWSLCG_WSI],
419*1c60b9acSAndroid Build Coastguard Worker                 	     &lsp->stdwsi[n]->lc, "nspawn-stdwsi-%d", n);
420*1c60b9acSAndroid Build Coastguard Worker 
421*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->lsp_channel = n;
422*1c60b9acSAndroid Build Coastguard Worker 		lws_vhost_bind_wsi(i->vh, lsp->stdwsi[n]);
423*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->a.protocol = pcol;
424*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->a.opaque_user_data = i->opaque;
425*1c60b9acSAndroid Build Coastguard Worker 
426*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->desc.filefd = lsp->pipe_fds[n][!n];
427*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->file_desc = 1;
428*1c60b9acSAndroid Build Coastguard Worker 
429*1c60b9acSAndroid Build Coastguard Worker 		lwsl_debug("%s: lsp stdwsi %p: pipe idx %d -> fd %d / %d\n",
430*1c60b9acSAndroid Build Coastguard Worker 			   __func__, lsp->stdwsi[n], n,
431*1c60b9acSAndroid Build Coastguard Worker 			   lsp->pipe_fds[n][!!(n == 0)],
432*1c60b9acSAndroid Build Coastguard Worker 			   lsp->pipe_fds[n][!(n == 0)]);
433*1c60b9acSAndroid Build Coastguard Worker 
434*1c60b9acSAndroid Build Coastguard Worker #if 0
435*1c60b9acSAndroid Build Coastguard Worker 
436*1c60b9acSAndroid Build Coastguard Worker 		/* read side is 0, stdin we want the write side, others read */
437*1c60b9acSAndroid Build Coastguard Worker 
438*1c60b9acSAndroid Build Coastguard Worker 		lsp->stdwsi[n]->desc.filefd = lsp->pipe_fds[n][!!(n == 0)];
439*1c60b9acSAndroid Build Coastguard Worker 		if (fcntl(lsp->pipe_fds[n][!!(n == 0)], F_SETFL, O_NONBLOCK) < 0) {
440*1c60b9acSAndroid Build Coastguard Worker 			lwsl_err("%s: setting NONBLOCK failed\n", __func__);
441*1c60b9acSAndroid Build Coastguard Worker 			goto bail2;
442*1c60b9acSAndroid Build Coastguard Worker 		}
443*1c60b9acSAndroid Build Coastguard Worker #endif
444*1c60b9acSAndroid Build Coastguard Worker 	}
445*1c60b9acSAndroid Build Coastguard Worker 
446*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++)
447*1c60b9acSAndroid Build Coastguard Worker 		if (i->opt_parent) {
448*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[n]->parent = i->opt_parent;
449*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[n]->sibling_list = i->opt_parent->child_list;
450*1c60b9acSAndroid Build Coastguard Worker 			i->opt_parent->child_list = lsp->stdwsi[n];
451*1c60b9acSAndroid Build Coastguard Worker 		}
452*1c60b9acSAndroid Build Coastguard Worker 
453*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: pipe handles in %p, out %p, err %p\n", __func__,
454*1c60b9acSAndroid Build Coastguard Worker 		   lsp->stdwsi[LWS_STDIN]->desc.sockfd,
455*1c60b9acSAndroid Build Coastguard Worker 		   lsp->stdwsi[LWS_STDOUT]->desc.sockfd,
456*1c60b9acSAndroid Build Coastguard Worker 		   lsp->stdwsi[LWS_STDERR]->desc.sockfd);
457*1c60b9acSAndroid Build Coastguard Worker 
458*1c60b9acSAndroid Build Coastguard Worker 	/*
459*1c60b9acSAndroid Build Coastguard Worker 	 * Windows nonblocking pipe handling is a mess that is unable
460*1c60b9acSAndroid Build Coastguard Worker 	 * to interoperate with WSA-based wait as far as I can tell.
461*1c60b9acSAndroid Build Coastguard Worker 	 *
462*1c60b9acSAndroid Build Coastguard Worker 	 * Let's set up a sul to poll the pipes and synthesize the
463*1c60b9acSAndroid Build Coastguard Worker 	 * protocol callbacks if anything coming.
464*1c60b9acSAndroid Build Coastguard Worker 	 */
465*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_schedule(context, 0, &lsp->sul_poll, windows_pipe_poll_hack,
466*1c60b9acSAndroid Build Coastguard Worker 			 50 * LWS_US_PER_MS);
467*1c60b9acSAndroid Build Coastguard Worker 
468*1c60b9acSAndroid Build Coastguard Worker 
469*1c60b9acSAndroid Build Coastguard Worker 	/*
470*1c60b9acSAndroid Build Coastguard Worker 	 * Windows wants a single string commandline
471*1c60b9acSAndroid Build Coastguard Worker 	 */
472*1c60b9acSAndroid Build Coastguard Worker 	p = cli;
473*1c60b9acSAndroid Build Coastguard Worker 	n = 0;
474*1c60b9acSAndroid Build Coastguard Worker 	while (i->exec_array[n]) {
475*1c60b9acSAndroid Build Coastguard Worker 		lws_strncpy(p, i->exec_array[n],
476*1c60b9acSAndroid Build Coastguard Worker 			    sizeof(cli) - lws_ptr_diff(p, cli));
477*1c60b9acSAndroid Build Coastguard Worker 		if (sizeof(cli) - lws_ptr_diff(p, cli) < 4)
478*1c60b9acSAndroid Build Coastguard Worker 			break;
479*1c60b9acSAndroid Build Coastguard Worker 		p += strlen(p);
480*1c60b9acSAndroid Build Coastguard Worker 		*p++ = ' ';
481*1c60b9acSAndroid Build Coastguard Worker 		*p = '\0';
482*1c60b9acSAndroid Build Coastguard Worker 		n++;
483*1c60b9acSAndroid Build Coastguard Worker 	}
484*1c60b9acSAndroid Build Coastguard Worker 
485*1c60b9acSAndroid Build Coastguard Worker 	puts(cli);
486*1c60b9acSAndroid Build Coastguard Worker 
487*1c60b9acSAndroid Build Coastguard Worker 	memset(&pi, 0, sizeof(pi));
488*1c60b9acSAndroid Build Coastguard Worker 	memset(&si, 0, sizeof(si));
489*1c60b9acSAndroid Build Coastguard Worker 
490*1c60b9acSAndroid Build Coastguard Worker 	si.cb		= sizeof(STARTUPINFO);
491*1c60b9acSAndroid Build Coastguard Worker 	si.hStdInput	= lsp->pipe_fds[LWS_STDIN][0];
492*1c60b9acSAndroid Build Coastguard Worker 	si.hStdOutput	= lsp->pipe_fds[LWS_STDOUT][1];
493*1c60b9acSAndroid Build Coastguard Worker 	si.hStdError	= lsp->pipe_fds[LWS_STDERR][1];
494*1c60b9acSAndroid Build Coastguard Worker 	si.dwFlags	= STARTF_USESTDHANDLES | CREATE_NO_WINDOW;
495*1c60b9acSAndroid Build Coastguard Worker 	si.wShowWindow	= TRUE;
496*1c60b9acSAndroid Build Coastguard Worker 
497*1c60b9acSAndroid Build Coastguard Worker 	if (!CreateProcess(NULL, cli, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
498*1c60b9acSAndroid Build Coastguard Worker 		lwsl_err("%s: CreateProcess failed 0x%x\n", __func__,
499*1c60b9acSAndroid Build Coastguard Worker 				(unsigned long)GetLastError());
500*1c60b9acSAndroid Build Coastguard Worker 		goto bail3;
501*1c60b9acSAndroid Build Coastguard Worker 	}
502*1c60b9acSAndroid Build Coastguard Worker 
503*1c60b9acSAndroid Build Coastguard Worker 	lsp->child_pid = pi.hProcess;
504*1c60b9acSAndroid Build Coastguard Worker 
505*1c60b9acSAndroid Build Coastguard Worker 	lwsl_notice("%s: lsp %p spawned PID %d\n", __func__, lsp, lsp->child_pid);
506*1c60b9acSAndroid Build Coastguard Worker 
507*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_schedule(context, i->tsi, &lsp->sul, lws_spawn_timeout,
508*1c60b9acSAndroid Build Coastguard Worker 			 i->timeout_us ? i->timeout_us : 300 * LWS_US_PER_SEC);
509*1c60b9acSAndroid Build Coastguard Worker 
510*1c60b9acSAndroid Build Coastguard Worker 	/*
511*1c60b9acSAndroid Build Coastguard Worker 	 *  close:                stdin:r, stdout:w, stderr:w
512*1c60b9acSAndroid Build Coastguard Worker 	 */
513*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++)
514*1c60b9acSAndroid Build Coastguard Worker 		CloseHandle(lsp->pipe_fds[n][n != 0]);
515*1c60b9acSAndroid Build Coastguard Worker 
516*1c60b9acSAndroid Build Coastguard Worker 	lsp->pipes_alive = 3;
517*1c60b9acSAndroid Build Coastguard Worker 	lsp->created = lws_now_usecs();
518*1c60b9acSAndroid Build Coastguard Worker 
519*1c60b9acSAndroid Build Coastguard Worker 	if (i->owner)
520*1c60b9acSAndroid Build Coastguard Worker 		lws_dll2_add_head(&lsp->dll, i->owner);
521*1c60b9acSAndroid Build Coastguard Worker 
522*1c60b9acSAndroid Build Coastguard Worker 	if (i->timeout_us)
523*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_schedule(context, i->tsi, &lsp->sul,
524*1c60b9acSAndroid Build Coastguard Worker 				 lws_spawn_timeout, i->timeout_us);
525*1c60b9acSAndroid Build Coastguard Worker 
526*1c60b9acSAndroid Build Coastguard Worker 	return lsp;
527*1c60b9acSAndroid Build Coastguard Worker 
528*1c60b9acSAndroid Build Coastguard Worker bail3:
529*1c60b9acSAndroid Build Coastguard Worker 
530*1c60b9acSAndroid Build Coastguard Worker 	lws_sul_cancel(&lsp->sul_poll);
531*1c60b9acSAndroid Build Coastguard Worker 
532*1c60b9acSAndroid Build Coastguard Worker 	while (--n >= 0)
533*1c60b9acSAndroid Build Coastguard Worker 		__remove_wsi_socket_from_fds(lsp->stdwsi[n]);
534*1c60b9acSAndroid Build Coastguard Worker bail2:
535*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++)
536*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->stdwsi[n])
537*1c60b9acSAndroid Build Coastguard Worker 			__lws_free_wsi(lsp->stdwsi[n]);
538*1c60b9acSAndroid Build Coastguard Worker 
539*1c60b9acSAndroid Build Coastguard Worker bail1:
540*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++) {
541*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->pipe_fds[n][0] >= 0)
542*1c60b9acSAndroid Build Coastguard Worker 			CloseHandle(lsp->pipe_fds[n][0]);
543*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->pipe_fds[n][1] >= 0)
544*1c60b9acSAndroid Build Coastguard Worker 			CloseHandle(lsp->pipe_fds[n][1]);
545*1c60b9acSAndroid Build Coastguard Worker 	}
546*1c60b9acSAndroid Build Coastguard Worker 
547*1c60b9acSAndroid Build Coastguard Worker 	lws_free(lsp);
548*1c60b9acSAndroid Build Coastguard Worker 
549*1c60b9acSAndroid Build Coastguard Worker 	lwsl_err("%s: failed\n", __func__);
550*1c60b9acSAndroid Build Coastguard Worker 
551*1c60b9acSAndroid Build Coastguard Worker 	return NULL;
552*1c60b9acSAndroid Build Coastguard Worker }
553*1c60b9acSAndroid Build Coastguard Worker 
554*1c60b9acSAndroid Build Coastguard Worker void
lws_spawn_stdwsi_closed(struct lws_spawn_piped * lsp,struct lws * wsi)555*1c60b9acSAndroid Build Coastguard Worker lws_spawn_stdwsi_closed(struct lws_spawn_piped *lsp, struct lws *wsi)
556*1c60b9acSAndroid Build Coastguard Worker {
557*1c60b9acSAndroid Build Coastguard Worker 	int n;
558*1c60b9acSAndroid Build Coastguard Worker 
559*1c60b9acSAndroid Build Coastguard Worker 	assert(lsp);
560*1c60b9acSAndroid Build Coastguard Worker 	lsp->pipes_alive--;
561*1c60b9acSAndroid Build Coastguard Worker 	lwsl_debug("%s: pipes alive %d\n", __func__, lsp->pipes_alive);
562*1c60b9acSAndroid Build Coastguard Worker 	if (!lsp->pipes_alive)
563*1c60b9acSAndroid Build Coastguard Worker 		lws_sul_schedule(lsp->info.vh->context, lsp->info.tsi,
564*1c60b9acSAndroid Build Coastguard Worker 				&lsp->sul_reap, lws_spawn_sul_reap, 1);
565*1c60b9acSAndroid Build Coastguard Worker 
566*1c60b9acSAndroid Build Coastguard Worker 	for (n = 0; n < 3; n++)
567*1c60b9acSAndroid Build Coastguard Worker 		if (lsp->stdwsi[n] == wsi)
568*1c60b9acSAndroid Build Coastguard Worker 			lsp->stdwsi[n] = NULL;
569*1c60b9acSAndroid Build Coastguard Worker }
570*1c60b9acSAndroid Build Coastguard Worker 
571*1c60b9acSAndroid Build Coastguard Worker int
lws_spawn_get_stdfd(struct lws * wsi)572*1c60b9acSAndroid Build Coastguard Worker lws_spawn_get_stdfd(struct lws *wsi)
573*1c60b9acSAndroid Build Coastguard Worker {
574*1c60b9acSAndroid Build Coastguard Worker 	return wsi->lsp_channel;
575*1c60b9acSAndroid Build Coastguard Worker }
576