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 - 2021 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 #include "private-lib-event-libs-libuv.h"
27*1c60b9acSAndroid Build Coastguard Worker
28*1c60b9acSAndroid Build Coastguard Worker #define pt_to_priv_uv(_pt) ((struct lws_pt_eventlibs_libuv *)(_pt)->evlib_pt)
29*1c60b9acSAndroid Build Coastguard Worker #define wsi_to_priv_uv(_w) ((struct lws_wsi_eventlibs_libuv *)(_w)->evlib_wsi)
30*1c60b9acSAndroid Build Coastguard Worker
31*1c60b9acSAndroid Build Coastguard Worker static void
lws_uv_sultimer_cb(uv_timer_t * timer,int status)32*1c60b9acSAndroid Build Coastguard Worker lws_uv_sultimer_cb(uv_timer_t *timer
33*1c60b9acSAndroid Build Coastguard Worker #if UV_VERSION_MAJOR == 0
34*1c60b9acSAndroid Build Coastguard Worker , int status
35*1c60b9acSAndroid Build Coastguard Worker #endif
36*1c60b9acSAndroid Build Coastguard Worker )
37*1c60b9acSAndroid Build Coastguard Worker {
38*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv *ptpr = lws_container_of(timer,
39*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv, sultimer);
40*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = ptpr->pt;
41*1c60b9acSAndroid Build Coastguard Worker lws_usec_t us;
42*1c60b9acSAndroid Build Coastguard Worker
43*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(pt->context, __func__);
44*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
45*1c60b9acSAndroid Build Coastguard Worker us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
46*1c60b9acSAndroid Build Coastguard Worker lws_now_usecs());
47*1c60b9acSAndroid Build Coastguard Worker if (us)
48*1c60b9acSAndroid Build Coastguard Worker uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb,
49*1c60b9acSAndroid Build Coastguard Worker LWS_US_TO_MS((uint64_t)us), 0);
50*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
51*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(pt->context);
52*1c60b9acSAndroid Build Coastguard Worker }
53*1c60b9acSAndroid Build Coastguard Worker
54*1c60b9acSAndroid Build Coastguard Worker static void
lws_uv_idle(uv_idle_t * handle,int status)55*1c60b9acSAndroid Build Coastguard Worker lws_uv_idle(uv_idle_t *handle
56*1c60b9acSAndroid Build Coastguard Worker #if UV_VERSION_MAJOR == 0
57*1c60b9acSAndroid Build Coastguard Worker , int status
58*1c60b9acSAndroid Build Coastguard Worker #endif
59*1c60b9acSAndroid Build Coastguard Worker )
60*1c60b9acSAndroid Build Coastguard Worker { struct lws_pt_eventlibs_libuv *ptpr = lws_container_of(handle,
61*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv, idle);
62*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = ptpr->pt;
63*1c60b9acSAndroid Build Coastguard Worker lws_usec_t us;
64*1c60b9acSAndroid Build Coastguard Worker
65*1c60b9acSAndroid Build Coastguard Worker lws_service_do_ripe_rxflow(pt);
66*1c60b9acSAndroid Build Coastguard Worker
67*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(pt->context, __func__);
68*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
69*1c60b9acSAndroid Build Coastguard Worker
70*1c60b9acSAndroid Build Coastguard Worker /*
71*1c60b9acSAndroid Build Coastguard Worker * is there anybody with pending stuff that needs service forcing?
72*1c60b9acSAndroid Build Coastguard Worker */
73*1c60b9acSAndroid Build Coastguard Worker if (!lws_service_adjust_timeout(pt->context, 1, pt->tid))
74*1c60b9acSAndroid Build Coastguard Worker /* -1 timeout means just do forced service */
75*1c60b9acSAndroid Build Coastguard Worker _lws_plat_service_forced_tsi(pt->context, pt->tid);
76*1c60b9acSAndroid Build Coastguard Worker
77*1c60b9acSAndroid Build Coastguard Worker /* account for sultimer */
78*1c60b9acSAndroid Build Coastguard Worker
79*1c60b9acSAndroid Build Coastguard Worker us = __lws_sul_service_ripe(pt->pt_sul_owner, LWS_COUNT_PT_SUL_OWNERS,
80*1c60b9acSAndroid Build Coastguard Worker lws_now_usecs());
81*1c60b9acSAndroid Build Coastguard Worker if (us)
82*1c60b9acSAndroid Build Coastguard Worker uv_timer_start(&pt_to_priv_uv(pt)->sultimer, lws_uv_sultimer_cb,
83*1c60b9acSAndroid Build Coastguard Worker LWS_US_TO_MS((uint64_t)us), 0);
84*1c60b9acSAndroid Build Coastguard Worker
85*1c60b9acSAndroid Build Coastguard Worker /* there is nobody who needs service forcing, shut down idle */
86*1c60b9acSAndroid Build Coastguard Worker uv_idle_stop(handle);
87*1c60b9acSAndroid Build Coastguard Worker
88*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
89*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(pt->context);
90*1c60b9acSAndroid Build Coastguard Worker }
91*1c60b9acSAndroid Build Coastguard Worker
92*1c60b9acSAndroid Build Coastguard Worker static void
lws_io_cb(uv_poll_t * watcher,int status,int revents)93*1c60b9acSAndroid Build Coastguard Worker lws_io_cb(uv_poll_t *watcher, int status, int revents)
94*1c60b9acSAndroid Build Coastguard Worker {
95*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi = (struct lws *)((uv_handle_t *)watcher)->data;
96*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = wsi->a.context;
97*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
98*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt);
99*1c60b9acSAndroid Build Coastguard Worker struct lws_pollfd eventfd;
100*1c60b9acSAndroid Build Coastguard Worker
101*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(pt->context, __func__);
102*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
103*1c60b9acSAndroid Build Coastguard Worker
104*1c60b9acSAndroid Build Coastguard Worker if (pt->is_destroyed)
105*1c60b9acSAndroid Build Coastguard Worker goto bail;
106*1c60b9acSAndroid Build Coastguard Worker
107*1c60b9acSAndroid Build Coastguard Worker if (!ptpriv->thread_valid) {
108*1c60b9acSAndroid Build Coastguard Worker /* record the thread id that gave us our first event */
109*1c60b9acSAndroid Build Coastguard Worker ptpriv->uv_thread = uv_thread_self();
110*1c60b9acSAndroid Build Coastguard Worker ptpriv->thread_valid = 1;
111*1c60b9acSAndroid Build Coastguard Worker }
112*1c60b9acSAndroid Build Coastguard Worker
113*1c60b9acSAndroid Build Coastguard Worker #if defined(WIN32) || defined(_WIN32)
114*1c60b9acSAndroid Build Coastguard Worker eventfd.fd = watcher->socket;
115*1c60b9acSAndroid Build Coastguard Worker #else
116*1c60b9acSAndroid Build Coastguard Worker eventfd.fd = watcher->io_watcher.fd;
117*1c60b9acSAndroid Build Coastguard Worker #endif
118*1c60b9acSAndroid Build Coastguard Worker eventfd.events = 0;
119*1c60b9acSAndroid Build Coastguard Worker eventfd.revents = 0;
120*1c60b9acSAndroid Build Coastguard Worker
121*1c60b9acSAndroid Build Coastguard Worker if (status < 0) {
122*1c60b9acSAndroid Build Coastguard Worker /*
123*1c60b9acSAndroid Build Coastguard Worker * At this point status will be an UV error, like UV_EBADF,
124*1c60b9acSAndroid Build Coastguard Worker * we treat all errors as LWS_POLLHUP
125*1c60b9acSAndroid Build Coastguard Worker *
126*1c60b9acSAndroid Build Coastguard Worker * You might want to return; instead of servicing the fd in
127*1c60b9acSAndroid Build Coastguard Worker * some cases */
128*1c60b9acSAndroid Build Coastguard Worker if (status == UV_EAGAIN)
129*1c60b9acSAndroid Build Coastguard Worker goto bail;
130*1c60b9acSAndroid Build Coastguard Worker
131*1c60b9acSAndroid Build Coastguard Worker eventfd.events |= LWS_POLLHUP;
132*1c60b9acSAndroid Build Coastguard Worker eventfd.revents |= LWS_POLLHUP;
133*1c60b9acSAndroid Build Coastguard Worker } else {
134*1c60b9acSAndroid Build Coastguard Worker if (revents & UV_READABLE) {
135*1c60b9acSAndroid Build Coastguard Worker eventfd.events |= LWS_POLLIN;
136*1c60b9acSAndroid Build Coastguard Worker eventfd.revents |= LWS_POLLIN;
137*1c60b9acSAndroid Build Coastguard Worker }
138*1c60b9acSAndroid Build Coastguard Worker if (revents & UV_WRITABLE) {
139*1c60b9acSAndroid Build Coastguard Worker eventfd.events |= LWS_POLLOUT;
140*1c60b9acSAndroid Build Coastguard Worker eventfd.revents |= LWS_POLLOUT;
141*1c60b9acSAndroid Build Coastguard Worker }
142*1c60b9acSAndroid Build Coastguard Worker }
143*1c60b9acSAndroid Build Coastguard Worker
144*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
145*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(pt->context);
146*1c60b9acSAndroid Build Coastguard Worker
147*1c60b9acSAndroid Build Coastguard Worker lws_service_fd_tsi(context, &eventfd, wsi->tsi);
148*1c60b9acSAndroid Build Coastguard Worker
149*1c60b9acSAndroid Build Coastguard Worker if (pt->destroy_self) {
150*1c60b9acSAndroid Build Coastguard Worker lws_context_destroy(pt->context);
151*1c60b9acSAndroid Build Coastguard Worker return;
152*1c60b9acSAndroid Build Coastguard Worker }
153*1c60b9acSAndroid Build Coastguard Worker
154*1c60b9acSAndroid Build Coastguard Worker uv_idle_start(&ptpriv->idle, lws_uv_idle);
155*1c60b9acSAndroid Build Coastguard Worker return;
156*1c60b9acSAndroid Build Coastguard Worker
157*1c60b9acSAndroid Build Coastguard Worker bail:
158*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
159*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(pt->context);
160*1c60b9acSAndroid Build Coastguard Worker }
161*1c60b9acSAndroid Build Coastguard Worker
162*1c60b9acSAndroid Build Coastguard Worker /*
163*1c60b9acSAndroid Build Coastguard Worker * This does not actually stop the event loop. The reason is we have to pass
164*1c60b9acSAndroid Build Coastguard Worker * libuv handle closures through its event loop. So this tries to close all
165*1c60b9acSAndroid Build Coastguard Worker * wsi, and set a flag; when all the wsi closures are finalized then we
166*1c60b9acSAndroid Build Coastguard Worker * actually stop the libuv event loops.
167*1c60b9acSAndroid Build Coastguard Worker */
168*1c60b9acSAndroid Build Coastguard Worker static void
lws_libuv_stop(struct lws_context * context)169*1c60b9acSAndroid Build Coastguard Worker lws_libuv_stop(struct lws_context *context)
170*1c60b9acSAndroid Build Coastguard Worker {
171*1c60b9acSAndroid Build Coastguard Worker if (context->requested_stop_internal_loops) {
172*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(context, "ignoring");
173*1c60b9acSAndroid Build Coastguard Worker return;
174*1c60b9acSAndroid Build Coastguard Worker }
175*1c60b9acSAndroid Build Coastguard Worker
176*1c60b9acSAndroid Build Coastguard Worker context->requested_stop_internal_loops = 1;
177*1c60b9acSAndroid Build Coastguard Worker lws_context_destroy(context);
178*1c60b9acSAndroid Build Coastguard Worker }
179*1c60b9acSAndroid Build Coastguard Worker
180*1c60b9acSAndroid Build Coastguard Worker static void
lws_uv_signal_handler(uv_signal_t * watcher,int signum)181*1c60b9acSAndroid Build Coastguard Worker lws_uv_signal_handler(uv_signal_t *watcher, int signum)
182*1c60b9acSAndroid Build Coastguard Worker {
183*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = (struct lws_context_per_thread *)
184*1c60b9acSAndroid Build Coastguard Worker watcher->data;
185*1c60b9acSAndroid Build Coastguard Worker
186*1c60b9acSAndroid Build Coastguard Worker if (pt->context->eventlib_signal_cb) {
187*1c60b9acSAndroid Build Coastguard Worker pt->context->eventlib_signal_cb((void *)watcher, signum);
188*1c60b9acSAndroid Build Coastguard Worker
189*1c60b9acSAndroid Build Coastguard Worker return;
190*1c60b9acSAndroid Build Coastguard Worker }
191*1c60b9acSAndroid Build Coastguard Worker
192*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(pt->context, "internal signal handler caught signal %d",
193*1c60b9acSAndroid Build Coastguard Worker signum);
194*1c60b9acSAndroid Build Coastguard Worker lws_libuv_stop(pt->context);
195*1c60b9acSAndroid Build Coastguard Worker }
196*1c60b9acSAndroid Build Coastguard Worker
197*1c60b9acSAndroid Build Coastguard Worker static int
lws_uv_finalize_pt(struct lws_context_per_thread * pt)198*1c60b9acSAndroid Build Coastguard Worker lws_uv_finalize_pt(struct lws_context_per_thread *pt)
199*1c60b9acSAndroid Build Coastguard Worker {
200*1c60b9acSAndroid Build Coastguard Worker pt->event_loop_pt_unused = 1;
201*1c60b9acSAndroid Build Coastguard Worker
202*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(pt->context, "thr %d", (int)(pt - pt->context->pt));
203*1c60b9acSAndroid Build Coastguard Worker
204*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(pt->context, __func__);
205*1c60b9acSAndroid Build Coastguard Worker
206*1c60b9acSAndroid Build Coastguard Worker if (!--pt->context->undestroyed_threads) {
207*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost *vh = pt->context->vhost_list;
208*1c60b9acSAndroid Build Coastguard Worker
209*1c60b9acSAndroid Build Coastguard Worker /*
210*1c60b9acSAndroid Build Coastguard Worker * eventually, we emptied all the pts...
211*1c60b9acSAndroid Build Coastguard Worker */
212*1c60b9acSAndroid Build Coastguard Worker
213*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_debug(pt->context, "all pts down now");
214*1c60b9acSAndroid Build Coastguard Worker
215*1c60b9acSAndroid Build Coastguard Worker /* protocols may have initialized libuv objects */
216*1c60b9acSAndroid Build Coastguard Worker
217*1c60b9acSAndroid Build Coastguard Worker while (vh) {
218*1c60b9acSAndroid Build Coastguard Worker lws_vhost_destroy1(vh);
219*1c60b9acSAndroid Build Coastguard Worker vh = vh->vhost_next;
220*1c60b9acSAndroid Build Coastguard Worker }
221*1c60b9acSAndroid Build Coastguard Worker
222*1c60b9acSAndroid Build Coastguard Worker if (!pt->count_event_loop_static_asset_handles &&
223*1c60b9acSAndroid Build Coastguard Worker pt->event_loop_foreign) {
224*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(pt->context, "resuming context_destroy");
225*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(pt->context);
226*1c60b9acSAndroid Build Coastguard Worker lws_context_destroy(pt->context);
227*1c60b9acSAndroid Build Coastguard Worker /*
228*1c60b9acSAndroid Build Coastguard Worker * For foreign, we're being called from the foreign
229*1c60b9acSAndroid Build Coastguard Worker * thread context the loop is associated with, we must
230*1c60b9acSAndroid Build Coastguard Worker * return to it cleanly even though we are done with it.
231*1c60b9acSAndroid Build Coastguard Worker */
232*1c60b9acSAndroid Build Coastguard Worker return 1;
233*1c60b9acSAndroid Build Coastguard Worker }
234*1c60b9acSAndroid Build Coastguard Worker } else
235*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_debug(pt->context, "still %d undestroyed",
236*1c60b9acSAndroid Build Coastguard Worker pt->context->undestroyed_threads);
237*1c60b9acSAndroid Build Coastguard Worker
238*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(pt->context);
239*1c60b9acSAndroid Build Coastguard Worker
240*1c60b9acSAndroid Build Coastguard Worker return 0;
241*1c60b9acSAndroid Build Coastguard Worker }
242*1c60b9acSAndroid Build Coastguard Worker
243*1c60b9acSAndroid Build Coastguard Worker // static void lws_uv_walk_cb(uv_handle_t *handle, void *arg)
244*1c60b9acSAndroid Build Coastguard Worker // {
245*1c60b9acSAndroid Build Coastguard Worker // if (!uv_is_closing(handle))
246*1c60b9acSAndroid Build Coastguard Worker // lwsl_err("%s: handle %p still alive on loop\n", __func__, handle);
247*1c60b9acSAndroid Build Coastguard Worker // }
248*1c60b9acSAndroid Build Coastguard Worker
249*1c60b9acSAndroid Build Coastguard Worker
250*1c60b9acSAndroid Build Coastguard Worker static const int sigs[] = { SIGINT, SIGTERM, SIGSEGV, SIGFPE, SIGHUP };
251*1c60b9acSAndroid Build Coastguard Worker
252*1c60b9acSAndroid Build Coastguard Worker /*
253*1c60b9acSAndroid Build Coastguard Worker * Closing Phase 2: Close callback for a static UV asset
254*1c60b9acSAndroid Build Coastguard Worker */
255*1c60b9acSAndroid Build Coastguard Worker
256*1c60b9acSAndroid Build Coastguard Worker static void
lws_uv_close_cb_sa(uv_handle_t * handle)257*1c60b9acSAndroid Build Coastguard Worker lws_uv_close_cb_sa(uv_handle_t *handle)
258*1c60b9acSAndroid Build Coastguard Worker {
259*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt =
260*1c60b9acSAndroid Build Coastguard Worker LWS_UV_REFCOUNT_STATIC_HANDLE_TO_PT(handle);
261*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt);
262*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = pt->context;
263*1c60b9acSAndroid Build Coastguard Worker #if !defined(LWS_WITH_NO_LOGS) && defined(_DEBUG)
264*1c60b9acSAndroid Build Coastguard Worker int tsi = (int)(pt - &context->pt[0]);
265*1c60b9acSAndroid Build Coastguard Worker #endif
266*1c60b9acSAndroid Build Coastguard Worker
267*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, "thr %d: sa left %d: dyn left: %d (rk %d)",
268*1c60b9acSAndroid Build Coastguard Worker tsi,
269*1c60b9acSAndroid Build Coastguard Worker pt->count_event_loop_static_asset_handles - 1,
270*1c60b9acSAndroid Build Coastguard Worker ptpriv->extant_handles,
271*1c60b9acSAndroid Build Coastguard Worker context->requested_stop_internal_loops);
272*1c60b9acSAndroid Build Coastguard Worker
273*1c60b9acSAndroid Build Coastguard Worker /* any static assets left? */
274*1c60b9acSAndroid Build Coastguard Worker
275*1c60b9acSAndroid Build Coastguard Worker if (LWS_UV_REFCOUNT_STATIC_HANDLE_DESTROYED(handle) ||
276*1c60b9acSAndroid Build Coastguard Worker ptpriv->extant_handles)
277*1c60b9acSAndroid Build Coastguard Worker return;
278*1c60b9acSAndroid Build Coastguard Worker
279*1c60b9acSAndroid Build Coastguard Worker /*
280*1c60b9acSAndroid Build Coastguard Worker * So we believe nothing of ours left on the loop. Let's sanity
281*1c60b9acSAndroid Build Coastguard Worker * check it to count what's still on the loop
282*1c60b9acSAndroid Build Coastguard Worker */
283*1c60b9acSAndroid Build Coastguard Worker
284*1c60b9acSAndroid Build Coastguard Worker // uv_walk(pt_to_priv_uv(pt)->io_loop, lws_uv_walk_cb, NULL);
285*1c60b9acSAndroid Build Coastguard Worker
286*1c60b9acSAndroid Build Coastguard Worker /*
287*1c60b9acSAndroid Build Coastguard Worker * That's it... all wsi were down, and now every
288*1c60b9acSAndroid Build Coastguard Worker * static asset lws had a UV handle for is down.
289*1c60b9acSAndroid Build Coastguard Worker *
290*1c60b9acSAndroid Build Coastguard Worker * Stop the loop so we can get out of here.
291*1c60b9acSAndroid Build Coastguard Worker */
292*1c60b9acSAndroid Build Coastguard Worker
293*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, "thr %d: seen final static handle gone", tsi);
294*1c60b9acSAndroid Build Coastguard Worker
295*1c60b9acSAndroid Build Coastguard Worker if (!pt->event_loop_foreign)
296*1c60b9acSAndroid Build Coastguard Worker lws_context_destroy(context);
297*1c60b9acSAndroid Build Coastguard Worker
298*1c60b9acSAndroid Build Coastguard Worker lws_uv_finalize_pt(pt);
299*1c60b9acSAndroid Build Coastguard Worker
300*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, "all done");
301*1c60b9acSAndroid Build Coastguard Worker }
302*1c60b9acSAndroid Build Coastguard Worker
303*1c60b9acSAndroid Build Coastguard Worker /*
304*1c60b9acSAndroid Build Coastguard Worker * These must be called by protocols that want to use libuv objects directly...
305*1c60b9acSAndroid Build Coastguard Worker *
306*1c60b9acSAndroid Build Coastguard Worker * .... when the libuv object is created...
307*1c60b9acSAndroid Build Coastguard Worker */
308*1c60b9acSAndroid Build Coastguard Worker
309*1c60b9acSAndroid Build Coastguard Worker void
lws_libuv_static_refcount_add(uv_handle_t * h,struct lws_context * context,int tsi)310*1c60b9acSAndroid Build Coastguard Worker lws_libuv_static_refcount_add(uv_handle_t *h, struct lws_context *context,
311*1c60b9acSAndroid Build Coastguard Worker int tsi)
312*1c60b9acSAndroid Build Coastguard Worker {
313*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[tsi];
314*1c60b9acSAndroid Build Coastguard Worker
315*1c60b9acSAndroid Build Coastguard Worker LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(h, pt);
316*1c60b9acSAndroid Build Coastguard Worker }
317*1c60b9acSAndroid Build Coastguard Worker
318*1c60b9acSAndroid Build Coastguard Worker /*
319*1c60b9acSAndroid Build Coastguard Worker * ... and in the close callback when the object is closed.
320*1c60b9acSAndroid Build Coastguard Worker */
321*1c60b9acSAndroid Build Coastguard Worker
322*1c60b9acSAndroid Build Coastguard Worker void
lws_libuv_static_refcount_del(uv_handle_t * h)323*1c60b9acSAndroid Build Coastguard Worker lws_libuv_static_refcount_del(uv_handle_t *h)
324*1c60b9acSAndroid Build Coastguard Worker {
325*1c60b9acSAndroid Build Coastguard Worker lws_uv_close_cb_sa(h);
326*1c60b9acSAndroid Build Coastguard Worker }
327*1c60b9acSAndroid Build Coastguard Worker
328*1c60b9acSAndroid Build Coastguard Worker void
lws_libuv_stop_without_kill(const struct lws_context * context,int tsi)329*1c60b9acSAndroid Build Coastguard Worker lws_libuv_stop_without_kill(const struct lws_context *context, int tsi)
330*1c60b9acSAndroid Build Coastguard Worker {
331*1c60b9acSAndroid Build Coastguard Worker if (pt_to_priv_uv(&context->pt[tsi])->io_loop)
332*1c60b9acSAndroid Build Coastguard Worker uv_stop(pt_to_priv_uv(&context->pt[tsi])->io_loop);
333*1c60b9acSAndroid Build Coastguard Worker }
334*1c60b9acSAndroid Build Coastguard Worker
335*1c60b9acSAndroid Build Coastguard Worker uv_loop_t *
lws_uv_getloop(struct lws_context * context,int tsi)336*1c60b9acSAndroid Build Coastguard Worker lws_uv_getloop(struct lws_context *context, int tsi)
337*1c60b9acSAndroid Build Coastguard Worker {
338*1c60b9acSAndroid Build Coastguard Worker if (pt_to_priv_uv(&context->pt[tsi])->io_loop)
339*1c60b9acSAndroid Build Coastguard Worker return pt_to_priv_uv(&context->pt[tsi])->io_loop;
340*1c60b9acSAndroid Build Coastguard Worker
341*1c60b9acSAndroid Build Coastguard Worker return NULL;
342*1c60b9acSAndroid Build Coastguard Worker }
343*1c60b9acSAndroid Build Coastguard Worker
344*1c60b9acSAndroid Build Coastguard Worker int
lws_libuv_check_watcher_active(struct lws * wsi)345*1c60b9acSAndroid Build Coastguard Worker lws_libuv_check_watcher_active(struct lws *wsi)
346*1c60b9acSAndroid Build Coastguard Worker {
347*1c60b9acSAndroid Build Coastguard Worker uv_handle_t *h = (uv_handle_t *)wsi_to_priv_uv(wsi)->w_read.pwatcher;
348*1c60b9acSAndroid Build Coastguard Worker
349*1c60b9acSAndroid Build Coastguard Worker if (!h)
350*1c60b9acSAndroid Build Coastguard Worker return 0;
351*1c60b9acSAndroid Build Coastguard Worker
352*1c60b9acSAndroid Build Coastguard Worker return uv_is_active(h);
353*1c60b9acSAndroid Build Coastguard Worker }
354*1c60b9acSAndroid Build Coastguard Worker
355*1c60b9acSAndroid Build Coastguard Worker static int
elops_init_context_uv(struct lws_context * context,const struct lws_context_creation_info * info)356*1c60b9acSAndroid Build Coastguard Worker elops_init_context_uv(struct lws_context *context,
357*1c60b9acSAndroid Build Coastguard Worker const struct lws_context_creation_info *info)
358*1c60b9acSAndroid Build Coastguard Worker {
359*1c60b9acSAndroid Build Coastguard Worker int n;
360*1c60b9acSAndroid Build Coastguard Worker
361*1c60b9acSAndroid Build Coastguard Worker context->eventlib_signal_cb = info->signal_cb;
362*1c60b9acSAndroid Build Coastguard Worker
363*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < context->count_threads; n++)
364*1c60b9acSAndroid Build Coastguard Worker pt_to_priv_uv(&context->pt[n])->w_sigint.context = context;
365*1c60b9acSAndroid Build Coastguard Worker
366*1c60b9acSAndroid Build Coastguard Worker return 0;
367*1c60b9acSAndroid Build Coastguard Worker }
368*1c60b9acSAndroid Build Coastguard Worker
369*1c60b9acSAndroid Build Coastguard Worker static int
elops_destroy_context1_uv(struct lws_context * context)370*1c60b9acSAndroid Build Coastguard Worker elops_destroy_context1_uv(struct lws_context *context)
371*1c60b9acSAndroid Build Coastguard Worker {
372*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt;
373*1c60b9acSAndroid Build Coastguard Worker int n, m = 0;
374*1c60b9acSAndroid Build Coastguard Worker
375*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < context->count_threads; n++) {
376*1c60b9acSAndroid Build Coastguard Worker int budget = 10000;
377*1c60b9acSAndroid Build Coastguard Worker pt = &context->pt[n];
378*1c60b9acSAndroid Build Coastguard Worker
379*1c60b9acSAndroid Build Coastguard Worker /* only for internal loops... */
380*1c60b9acSAndroid Build Coastguard Worker
381*1c60b9acSAndroid Build Coastguard Worker if (!pt->event_loop_foreign) {
382*1c60b9acSAndroid Build Coastguard Worker
383*1c60b9acSAndroid Build Coastguard Worker while (budget-- && (m = uv_run(pt_to_priv_uv(pt)->io_loop,
384*1c60b9acSAndroid Build Coastguard Worker UV_RUN_NOWAIT)))
385*1c60b9acSAndroid Build Coastguard Worker ;
386*1c60b9acSAndroid Build Coastguard Worker if (m)
387*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_info(context, "tsi %d: unclosed", n);
388*1c60b9acSAndroid Build Coastguard Worker
389*1c60b9acSAndroid Build Coastguard Worker }
390*1c60b9acSAndroid Build Coastguard Worker }
391*1c60b9acSAndroid Build Coastguard Worker
392*1c60b9acSAndroid Build Coastguard Worker /* call destroy2 if internal loop */
393*1c60b9acSAndroid Build Coastguard Worker return !context->pt[0].event_loop_foreign;
394*1c60b9acSAndroid Build Coastguard Worker }
395*1c60b9acSAndroid Build Coastguard Worker
396*1c60b9acSAndroid Build Coastguard Worker static int
elops_destroy_context2_uv(struct lws_context * context)397*1c60b9acSAndroid Build Coastguard Worker elops_destroy_context2_uv(struct lws_context *context)
398*1c60b9acSAndroid Build Coastguard Worker {
399*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt;
400*1c60b9acSAndroid Build Coastguard Worker int n, internal = 0;
401*1c60b9acSAndroid Build Coastguard Worker
402*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < context->count_threads; n++) {
403*1c60b9acSAndroid Build Coastguard Worker pt = &context->pt[n];
404*1c60b9acSAndroid Build Coastguard Worker
405*1c60b9acSAndroid Build Coastguard Worker /* only for internal loops... */
406*1c60b9acSAndroid Build Coastguard Worker
407*1c60b9acSAndroid Build Coastguard Worker if (!pt->event_loop_foreign && pt_to_priv_uv(pt)->io_loop) {
408*1c60b9acSAndroid Build Coastguard Worker internal = 1;
409*1c60b9acSAndroid Build Coastguard Worker if (!context->evlib_finalize_destroy_after_int_loops_stop)
410*1c60b9acSAndroid Build Coastguard Worker uv_stop(pt_to_priv_uv(pt)->io_loop);
411*1c60b9acSAndroid Build Coastguard Worker else {
412*1c60b9acSAndroid Build Coastguard Worker #if UV_VERSION_MAJOR > 0
413*1c60b9acSAndroid Build Coastguard Worker uv_loop_close(pt_to_priv_uv(pt)->io_loop);
414*1c60b9acSAndroid Build Coastguard Worker #endif
415*1c60b9acSAndroid Build Coastguard Worker lws_free_set_NULL(pt_to_priv_uv(pt)->io_loop);
416*1c60b9acSAndroid Build Coastguard Worker }
417*1c60b9acSAndroid Build Coastguard Worker }
418*1c60b9acSAndroid Build Coastguard Worker }
419*1c60b9acSAndroid Build Coastguard Worker
420*1c60b9acSAndroid Build Coastguard Worker return internal;
421*1c60b9acSAndroid Build Coastguard Worker }
422*1c60b9acSAndroid Build Coastguard Worker
423*1c60b9acSAndroid Build Coastguard Worker static int
elops_wsi_logical_close_uv(struct lws * wsi)424*1c60b9acSAndroid Build Coastguard Worker elops_wsi_logical_close_uv(struct lws *wsi)
425*1c60b9acSAndroid Build Coastguard Worker {
426*1c60b9acSAndroid Build Coastguard Worker if (!lws_socket_is_valid(wsi->desc.sockfd) &&
427*1c60b9acSAndroid Build Coastguard Worker wsi->role_ops && strcmp(wsi->role_ops->name, "raw-file") &&
428*1c60b9acSAndroid Build Coastguard Worker !wsi_to_priv_uv(wsi)->w_read.pwatcher)
429*1c60b9acSAndroid Build Coastguard Worker return 0;
430*1c60b9acSAndroid Build Coastguard Worker
431*1c60b9acSAndroid Build Coastguard Worker if (wsi->listener || wsi->event_pipe) {
432*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "%d %d stop listener / pipe poll",
433*1c60b9acSAndroid Build Coastguard Worker wsi->listener,
434*1c60b9acSAndroid Build Coastguard Worker wsi->event_pipe);
435*1c60b9acSAndroid Build Coastguard Worker if (wsi_to_priv_uv(wsi)->w_read.pwatcher)
436*1c60b9acSAndroid Build Coastguard Worker uv_poll_stop(wsi_to_priv_uv(wsi)->w_read.pwatcher);
437*1c60b9acSAndroid Build Coastguard Worker }
438*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "lws_libuv_closehandle");
439*1c60b9acSAndroid Build Coastguard Worker /*
440*1c60b9acSAndroid Build Coastguard Worker * libuv has to do his own close handle processing asynchronously
441*1c60b9acSAndroid Build Coastguard Worker */
442*1c60b9acSAndroid Build Coastguard Worker lws_libuv_closehandle(wsi);
443*1c60b9acSAndroid Build Coastguard Worker
444*1c60b9acSAndroid Build Coastguard Worker return 1; /* do not complete the wsi close, uv close cb will do it */
445*1c60b9acSAndroid Build Coastguard Worker }
446*1c60b9acSAndroid Build Coastguard Worker
447*1c60b9acSAndroid Build Coastguard Worker static int
elops_check_client_connect_ok_uv(struct lws * wsi)448*1c60b9acSAndroid Build Coastguard Worker elops_check_client_connect_ok_uv(struct lws *wsi)
449*1c60b9acSAndroid Build Coastguard Worker {
450*1c60b9acSAndroid Build Coastguard Worker if (lws_libuv_check_watcher_active(wsi)) {
451*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_warn(wsi, "Waiting for libuv watcher to close");
452*1c60b9acSAndroid Build Coastguard Worker return 1;
453*1c60b9acSAndroid Build Coastguard Worker }
454*1c60b9acSAndroid Build Coastguard Worker
455*1c60b9acSAndroid Build Coastguard Worker return 0;
456*1c60b9acSAndroid Build Coastguard Worker }
457*1c60b9acSAndroid Build Coastguard Worker
458*1c60b9acSAndroid Build Coastguard Worker static void
lws_libuv_closewsi_m(uv_handle_t * handle)459*1c60b9acSAndroid Build Coastguard Worker lws_libuv_closewsi_m(uv_handle_t* handle)
460*1c60b9acSAndroid Build Coastguard Worker {
461*1c60b9acSAndroid Build Coastguard Worker lws_sockfd_type sockfd = (lws_sockfd_type)(lws_intptr_t)handle->data;
462*1c60b9acSAndroid Build Coastguard Worker
463*1c60b9acSAndroid Build Coastguard Worker lwsl_debug("%s: sockfd %d\n", __func__, sockfd);
464*1c60b9acSAndroid Build Coastguard Worker compatible_close(sockfd);
465*1c60b9acSAndroid Build Coastguard Worker lws_free(handle);
466*1c60b9acSAndroid Build Coastguard Worker }
467*1c60b9acSAndroid Build Coastguard Worker
468*1c60b9acSAndroid Build Coastguard Worker static void
elops_close_handle_manually_uv(struct lws * wsi)469*1c60b9acSAndroid Build Coastguard Worker elops_close_handle_manually_uv(struct lws *wsi)
470*1c60b9acSAndroid Build Coastguard Worker {
471*1c60b9acSAndroid Build Coastguard Worker uv_handle_t *h = (uv_handle_t *)wsi_to_priv_uv(wsi)->w_read.pwatcher;
472*1c60b9acSAndroid Build Coastguard Worker
473*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "lws_libuv_closehandle");
474*1c60b9acSAndroid Build Coastguard Worker
475*1c60b9acSAndroid Build Coastguard Worker /*
476*1c60b9acSAndroid Build Coastguard Worker * the "manual" variant only closes the handle itself and the
477*1c60b9acSAndroid Build Coastguard Worker * related fd. handle->data is the fd.
478*1c60b9acSAndroid Build Coastguard Worker */
479*1c60b9acSAndroid Build Coastguard Worker h->data = (void *)(lws_intptr_t)wsi->desc.sockfd;
480*1c60b9acSAndroid Build Coastguard Worker
481*1c60b9acSAndroid Build Coastguard Worker /*
482*1c60b9acSAndroid Build Coastguard Worker * We take responsibility to close / destroy these now.
483*1c60b9acSAndroid Build Coastguard Worker * Remove any trace from the wsi.
484*1c60b9acSAndroid Build Coastguard Worker */
485*1c60b9acSAndroid Build Coastguard Worker
486*1c60b9acSAndroid Build Coastguard Worker wsi->desc.sockfd = LWS_SOCK_INVALID;
487*1c60b9acSAndroid Build Coastguard Worker wsi_to_priv_uv(wsi)->w_read.pwatcher = NULL;
488*1c60b9acSAndroid Build Coastguard Worker wsi->told_event_loop_closed = 1;
489*1c60b9acSAndroid Build Coastguard Worker
490*1c60b9acSAndroid Build Coastguard Worker uv_close(h, lws_libuv_closewsi_m);
491*1c60b9acSAndroid Build Coastguard Worker }
492*1c60b9acSAndroid Build Coastguard Worker
493*1c60b9acSAndroid Build Coastguard Worker static int
elops_accept_uv(struct lws * wsi)494*1c60b9acSAndroid Build Coastguard Worker elops_accept_uv(struct lws *wsi)
495*1c60b9acSAndroid Build Coastguard Worker {
496*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
497*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt);
498*1c60b9acSAndroid Build Coastguard Worker struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read;
499*1c60b9acSAndroid Build Coastguard Worker int n;
500*1c60b9acSAndroid Build Coastguard Worker
501*1c60b9acSAndroid Build Coastguard Worker if (!ptpriv->thread_valid) {
502*1c60b9acSAndroid Build Coastguard Worker /* record the thread id that gave us our first event */
503*1c60b9acSAndroid Build Coastguard Worker ptpriv->uv_thread = uv_thread_self();
504*1c60b9acSAndroid Build Coastguard Worker ptpriv->thread_valid = 1;
505*1c60b9acSAndroid Build Coastguard Worker }
506*1c60b9acSAndroid Build Coastguard Worker
507*1c60b9acSAndroid Build Coastguard Worker w_read->context = wsi->a.context;
508*1c60b9acSAndroid Build Coastguard Worker
509*1c60b9acSAndroid Build Coastguard Worker w_read->pwatcher = lws_malloc(sizeof(*w_read->pwatcher), "uvh");
510*1c60b9acSAndroid Build Coastguard Worker if (!w_read->pwatcher)
511*1c60b9acSAndroid Build Coastguard Worker return -1;
512*1c60b9acSAndroid Build Coastguard Worker
513*1c60b9acSAndroid Build Coastguard Worker if (wsi->role_ops->file_handle)
514*1c60b9acSAndroid Build Coastguard Worker n = uv_poll_init(pt_to_priv_uv(pt)->io_loop, w_read->pwatcher,
515*1c60b9acSAndroid Build Coastguard Worker (int)(lws_intptr_t)wsi->desc.filefd);
516*1c60b9acSAndroid Build Coastguard Worker else
517*1c60b9acSAndroid Build Coastguard Worker n = uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop,
518*1c60b9acSAndroid Build Coastguard Worker w_read->pwatcher, wsi->desc.sockfd);
519*1c60b9acSAndroid Build Coastguard Worker
520*1c60b9acSAndroid Build Coastguard Worker if (n) {
521*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_err(wsi, "uv_poll_init failed %d, sockfd=%p", n,
522*1c60b9acSAndroid Build Coastguard Worker (void *)(lws_intptr_t)wsi->desc.sockfd);
523*1c60b9acSAndroid Build Coastguard Worker lws_free(w_read->pwatcher);
524*1c60b9acSAndroid Build Coastguard Worker w_read->pwatcher = NULL;
525*1c60b9acSAndroid Build Coastguard Worker return -1;
526*1c60b9acSAndroid Build Coastguard Worker }
527*1c60b9acSAndroid Build Coastguard Worker
528*1c60b9acSAndroid Build Coastguard Worker ((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi;
529*1c60b9acSAndroid Build Coastguard Worker
530*1c60b9acSAndroid Build Coastguard Worker ptpriv->extant_handles++;
531*1c60b9acSAndroid Build Coastguard Worker
532*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "thr %d: sa left %d: dyn left: %d",
533*1c60b9acSAndroid Build Coastguard Worker (int)(pt - &pt->context->pt[0]),
534*1c60b9acSAndroid Build Coastguard Worker pt->count_event_loop_static_asset_handles,
535*1c60b9acSAndroid Build Coastguard Worker ptpriv->extant_handles);
536*1c60b9acSAndroid Build Coastguard Worker
537*1c60b9acSAndroid Build Coastguard Worker return 0;
538*1c60b9acSAndroid Build Coastguard Worker }
539*1c60b9acSAndroid Build Coastguard Worker
540*1c60b9acSAndroid Build Coastguard Worker static void
elops_io_uv(struct lws * wsi,unsigned int flags)541*1c60b9acSAndroid Build Coastguard Worker elops_io_uv(struct lws *wsi, unsigned int flags)
542*1c60b9acSAndroid Build Coastguard Worker {
543*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
544*1c60b9acSAndroid Build Coastguard Worker struct lws_io_watcher_libuv *w = &(wsi_to_priv_uv(wsi)->w_read);
545*1c60b9acSAndroid Build Coastguard Worker int current_events = w->actual_events & (UV_READABLE | UV_WRITABLE);
546*1c60b9acSAndroid Build Coastguard Worker
547*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "%d", flags);
548*1c60b9acSAndroid Build Coastguard Worker
549*1c60b9acSAndroid Build Coastguard Worker /* w->context is set after the loop is initialized */
550*1c60b9acSAndroid Build Coastguard Worker
551*1c60b9acSAndroid Build Coastguard Worker if (!pt_to_priv_uv(pt)->io_loop || !w->context) {
552*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "no io loop yet");
553*1c60b9acSAndroid Build Coastguard Worker return;
554*1c60b9acSAndroid Build Coastguard Worker }
555*1c60b9acSAndroid Build Coastguard Worker
556*1c60b9acSAndroid Build Coastguard Worker if (!((flags & (LWS_EV_START | LWS_EV_STOP)) &&
557*1c60b9acSAndroid Build Coastguard Worker (flags & (LWS_EV_READ | LWS_EV_WRITE)))) {
558*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_err(wsi, "assert: flags %d", flags);
559*1c60b9acSAndroid Build Coastguard Worker assert(0);
560*1c60b9acSAndroid Build Coastguard Worker }
561*1c60b9acSAndroid Build Coastguard Worker
562*1c60b9acSAndroid Build Coastguard Worker if (!w->pwatcher || wsi->told_event_loop_closed) {
563*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "no watcher");
564*1c60b9acSAndroid Build Coastguard Worker
565*1c60b9acSAndroid Build Coastguard Worker return;
566*1c60b9acSAndroid Build Coastguard Worker }
567*1c60b9acSAndroid Build Coastguard Worker
568*1c60b9acSAndroid Build Coastguard Worker if (flags & LWS_EV_START) {
569*1c60b9acSAndroid Build Coastguard Worker if (flags & LWS_EV_WRITE)
570*1c60b9acSAndroid Build Coastguard Worker current_events |= UV_WRITABLE;
571*1c60b9acSAndroid Build Coastguard Worker
572*1c60b9acSAndroid Build Coastguard Worker if (flags & LWS_EV_READ)
573*1c60b9acSAndroid Build Coastguard Worker current_events |= UV_READABLE;
574*1c60b9acSAndroid Build Coastguard Worker
575*1c60b9acSAndroid Build Coastguard Worker uv_poll_start(w->pwatcher, current_events, lws_io_cb);
576*1c60b9acSAndroid Build Coastguard Worker } else {
577*1c60b9acSAndroid Build Coastguard Worker if (flags & LWS_EV_WRITE)
578*1c60b9acSAndroid Build Coastguard Worker current_events &= ~UV_WRITABLE;
579*1c60b9acSAndroid Build Coastguard Worker
580*1c60b9acSAndroid Build Coastguard Worker if (flags & LWS_EV_READ)
581*1c60b9acSAndroid Build Coastguard Worker current_events &= ~UV_READABLE;
582*1c60b9acSAndroid Build Coastguard Worker
583*1c60b9acSAndroid Build Coastguard Worker if (!(current_events & (UV_READABLE | UV_WRITABLE)))
584*1c60b9acSAndroid Build Coastguard Worker uv_poll_stop(w->pwatcher);
585*1c60b9acSAndroid Build Coastguard Worker else
586*1c60b9acSAndroid Build Coastguard Worker uv_poll_start(w->pwatcher, current_events, lws_io_cb);
587*1c60b9acSAndroid Build Coastguard Worker }
588*1c60b9acSAndroid Build Coastguard Worker
589*1c60b9acSAndroid Build Coastguard Worker w->actual_events = (uint8_t)current_events;
590*1c60b9acSAndroid Build Coastguard Worker }
591*1c60b9acSAndroid Build Coastguard Worker
592*1c60b9acSAndroid Build Coastguard Worker static int
elops_init_vhost_listen_wsi_uv(struct lws * wsi)593*1c60b9acSAndroid Build Coastguard Worker elops_init_vhost_listen_wsi_uv(struct lws *wsi)
594*1c60b9acSAndroid Build Coastguard Worker {
595*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt;
596*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv *ptpriv;
597*1c60b9acSAndroid Build Coastguard Worker struct lws_io_watcher_libuv *w_read;
598*1c60b9acSAndroid Build Coastguard Worker int n;
599*1c60b9acSAndroid Build Coastguard Worker
600*1c60b9acSAndroid Build Coastguard Worker if (!wsi)
601*1c60b9acSAndroid Build Coastguard Worker return 0;
602*1c60b9acSAndroid Build Coastguard Worker
603*1c60b9acSAndroid Build Coastguard Worker w_read = &wsi_to_priv_uv(wsi)->w_read;
604*1c60b9acSAndroid Build Coastguard Worker
605*1c60b9acSAndroid Build Coastguard Worker if (w_read->context)
606*1c60b9acSAndroid Build Coastguard Worker return 0;
607*1c60b9acSAndroid Build Coastguard Worker
608*1c60b9acSAndroid Build Coastguard Worker pt = &wsi->a.context->pt[(int)wsi->tsi];
609*1c60b9acSAndroid Build Coastguard Worker ptpriv = pt_to_priv_uv(pt);
610*1c60b9acSAndroid Build Coastguard Worker if (!ptpriv->io_loop)
611*1c60b9acSAndroid Build Coastguard Worker return 0;
612*1c60b9acSAndroid Build Coastguard Worker
613*1c60b9acSAndroid Build Coastguard Worker w_read->context = wsi->a.context;
614*1c60b9acSAndroid Build Coastguard Worker
615*1c60b9acSAndroid Build Coastguard Worker w_read->pwatcher = lws_malloc(sizeof(*w_read->pwatcher), "uvh");
616*1c60b9acSAndroid Build Coastguard Worker if (!w_read->pwatcher)
617*1c60b9acSAndroid Build Coastguard Worker return -1;
618*1c60b9acSAndroid Build Coastguard Worker
619*1c60b9acSAndroid Build Coastguard Worker n = uv_poll_init_socket(pt_to_priv_uv(pt)->io_loop,
620*1c60b9acSAndroid Build Coastguard Worker w_read->pwatcher, wsi->desc.sockfd);
621*1c60b9acSAndroid Build Coastguard Worker if (n) {
622*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_err(wsi, "uv_poll_init failed %d, sockfd=%p", n,
623*1c60b9acSAndroid Build Coastguard Worker (void *)(lws_intptr_t)wsi->desc.sockfd);
624*1c60b9acSAndroid Build Coastguard Worker
625*1c60b9acSAndroid Build Coastguard Worker return -1;
626*1c60b9acSAndroid Build Coastguard Worker }
627*1c60b9acSAndroid Build Coastguard Worker
628*1c60b9acSAndroid Build Coastguard Worker ptpriv->extant_handles++;
629*1c60b9acSAndroid Build Coastguard Worker
630*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_debug(wsi, "thr %d: sa left %d: dyn left: %d",
631*1c60b9acSAndroid Build Coastguard Worker (int)(pt - &pt->context->pt[0]),
632*1c60b9acSAndroid Build Coastguard Worker pt->count_event_loop_static_asset_handles,
633*1c60b9acSAndroid Build Coastguard Worker ptpriv->extant_handles);
634*1c60b9acSAndroid Build Coastguard Worker
635*1c60b9acSAndroid Build Coastguard Worker ((uv_handle_t *)w_read->pwatcher)->data = (void *)wsi;
636*1c60b9acSAndroid Build Coastguard Worker
637*1c60b9acSAndroid Build Coastguard Worker elops_io_uv(wsi, LWS_EV_START | LWS_EV_READ);
638*1c60b9acSAndroid Build Coastguard Worker
639*1c60b9acSAndroid Build Coastguard Worker return 0;
640*1c60b9acSAndroid Build Coastguard Worker }
641*1c60b9acSAndroid Build Coastguard Worker
642*1c60b9acSAndroid Build Coastguard Worker static void
elops_run_pt_uv(struct lws_context * context,int tsi)643*1c60b9acSAndroid Build Coastguard Worker elops_run_pt_uv(struct lws_context *context, int tsi)
644*1c60b9acSAndroid Build Coastguard Worker {
645*1c60b9acSAndroid Build Coastguard Worker if (pt_to_priv_uv(&context->pt[tsi])->io_loop)
646*1c60b9acSAndroid Build Coastguard Worker uv_run(pt_to_priv_uv(&context->pt[tsi])->io_loop, 0);
647*1c60b9acSAndroid Build Coastguard Worker }
648*1c60b9acSAndroid Build Coastguard Worker
649*1c60b9acSAndroid Build Coastguard Worker static void
elops_destroy_pt_uv(struct lws_context * context,int tsi)650*1c60b9acSAndroid Build Coastguard Worker elops_destroy_pt_uv(struct lws_context *context, int tsi)
651*1c60b9acSAndroid Build Coastguard Worker {
652*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[tsi];
653*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt);
654*1c60b9acSAndroid Build Coastguard Worker int m, ns;
655*1c60b9acSAndroid Build Coastguard Worker
656*1c60b9acSAndroid Build Coastguard Worker if (!lws_check_opt(context->options, LWS_SERVER_OPTION_LIBUV))
657*1c60b9acSAndroid Build Coastguard Worker return;
658*1c60b9acSAndroid Build Coastguard Worker
659*1c60b9acSAndroid Build Coastguard Worker if (!ptpriv->io_loop)
660*1c60b9acSAndroid Build Coastguard Worker return;
661*1c60b9acSAndroid Build Coastguard Worker
662*1c60b9acSAndroid Build Coastguard Worker if (pt->event_loop_destroy_processing_done) {
663*1c60b9acSAndroid Build Coastguard Worker if (!pt->event_loop_foreign) {
664*1c60b9acSAndroid Build Coastguard Worker lwsl_warn("%s: stopping event loop\n", __func__);
665*1c60b9acSAndroid Build Coastguard Worker uv_stop(pt_to_priv_uv(pt)->io_loop);
666*1c60b9acSAndroid Build Coastguard Worker }
667*1c60b9acSAndroid Build Coastguard Worker return;
668*1c60b9acSAndroid Build Coastguard Worker }
669*1c60b9acSAndroid Build Coastguard Worker
670*1c60b9acSAndroid Build Coastguard Worker pt->event_loop_destroy_processing_done = 1;
671*1c60b9acSAndroid Build Coastguard Worker // lwsl_cx_debug(context, "%d", tsi);
672*1c60b9acSAndroid Build Coastguard Worker
673*1c60b9acSAndroid Build Coastguard Worker if (!pt->event_loop_foreign) {
674*1c60b9acSAndroid Build Coastguard Worker
675*1c60b9acSAndroid Build Coastguard Worker uv_signal_stop(&pt_to_priv_uv(pt)->w_sigint.watcher);
676*1c60b9acSAndroid Build Coastguard Worker
677*1c60b9acSAndroid Build Coastguard Worker ns = LWS_ARRAY_SIZE(sigs);
678*1c60b9acSAndroid Build Coastguard Worker if (lws_check_opt(context->options,
679*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN))
680*1c60b9acSAndroid Build Coastguard Worker ns = 2;
681*1c60b9acSAndroid Build Coastguard Worker
682*1c60b9acSAndroid Build Coastguard Worker for (m = 0; m < ns; m++) {
683*1c60b9acSAndroid Build Coastguard Worker uv_signal_stop(&pt_to_priv_uv(pt)->signals[m]);
684*1c60b9acSAndroid Build Coastguard Worker uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->signals[m],
685*1c60b9acSAndroid Build Coastguard Worker lws_uv_close_cb_sa);
686*1c60b9acSAndroid Build Coastguard Worker }
687*1c60b9acSAndroid Build Coastguard Worker } else
688*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_debug(context, "not closing pt signals");
689*1c60b9acSAndroid Build Coastguard Worker
690*1c60b9acSAndroid Build Coastguard Worker uv_timer_stop(&pt_to_priv_uv(pt)->sultimer);
691*1c60b9acSAndroid Build Coastguard Worker uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->sultimer, lws_uv_close_cb_sa);
692*1c60b9acSAndroid Build Coastguard Worker
693*1c60b9acSAndroid Build Coastguard Worker uv_idle_stop(&pt_to_priv_uv(pt)->idle);
694*1c60b9acSAndroid Build Coastguard Worker uv_close((uv_handle_t *)&pt_to_priv_uv(pt)->idle, lws_uv_close_cb_sa);
695*1c60b9acSAndroid Build Coastguard Worker }
696*1c60b9acSAndroid Build Coastguard Worker
697*1c60b9acSAndroid Build Coastguard Worker static int
elops_listen_init_uv(struct lws_dll2 * d,void * user)698*1c60b9acSAndroid Build Coastguard Worker elops_listen_init_uv(struct lws_dll2 *d, void *user)
699*1c60b9acSAndroid Build Coastguard Worker {
700*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi = lws_container_of(d, struct lws, listen_list);
701*1c60b9acSAndroid Build Coastguard Worker
702*1c60b9acSAndroid Build Coastguard Worker if (elops_init_vhost_listen_wsi_uv(wsi) == -1)
703*1c60b9acSAndroid Build Coastguard Worker return -1;
704*1c60b9acSAndroid Build Coastguard Worker
705*1c60b9acSAndroid Build Coastguard Worker return 0;
706*1c60b9acSAndroid Build Coastguard Worker }
707*1c60b9acSAndroid Build Coastguard Worker
708*1c60b9acSAndroid Build Coastguard Worker /*
709*1c60b9acSAndroid Build Coastguard Worker * This needs to be called after vhosts have been defined.
710*1c60b9acSAndroid Build Coastguard Worker *
711*1c60b9acSAndroid Build Coastguard Worker * If later, after server start, another vhost is added, this must be
712*1c60b9acSAndroid Build Coastguard Worker * called again to bind the vhost
713*1c60b9acSAndroid Build Coastguard Worker */
714*1c60b9acSAndroid Build Coastguard Worker
715*1c60b9acSAndroid Build Coastguard Worker int
elops_init_pt_uv(struct lws_context * context,void * _loop,int tsi)716*1c60b9acSAndroid Build Coastguard Worker elops_init_pt_uv(struct lws_context *context, void *_loop, int tsi)
717*1c60b9acSAndroid Build Coastguard Worker {
718*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[tsi];
719*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt);
720*1c60b9acSAndroid Build Coastguard Worker int status = 0, n, ns, first = 1;
721*1c60b9acSAndroid Build Coastguard Worker uv_loop_t *loop = (uv_loop_t *)_loop;
722*1c60b9acSAndroid Build Coastguard Worker
723*1c60b9acSAndroid Build Coastguard Worker ptpriv->pt = pt;
724*1c60b9acSAndroid Build Coastguard Worker
725*1c60b9acSAndroid Build Coastguard Worker if (!ptpriv->io_loop) {
726*1c60b9acSAndroid Build Coastguard Worker if (!loop) {
727*1c60b9acSAndroid Build Coastguard Worker loop = lws_malloc(sizeof(*loop), "libuv loop");
728*1c60b9acSAndroid Build Coastguard Worker if (!loop) {
729*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(context, "OOM");
730*1c60b9acSAndroid Build Coastguard Worker return -1;
731*1c60b9acSAndroid Build Coastguard Worker }
732*1c60b9acSAndroid Build Coastguard Worker #if UV_VERSION_MAJOR > 0
733*1c60b9acSAndroid Build Coastguard Worker uv_loop_init(loop);
734*1c60b9acSAndroid Build Coastguard Worker #else
735*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_err(context, "This libuv is too old to work...");
736*1c60b9acSAndroid Build Coastguard Worker return 1;
737*1c60b9acSAndroid Build Coastguard Worker #endif
738*1c60b9acSAndroid Build Coastguard Worker pt->event_loop_foreign = 0;
739*1c60b9acSAndroid Build Coastguard Worker } else {
740*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_notice(context, " Using foreign event loop...");
741*1c60b9acSAndroid Build Coastguard Worker pt->event_loop_foreign = 1;
742*1c60b9acSAndroid Build Coastguard Worker }
743*1c60b9acSAndroid Build Coastguard Worker
744*1c60b9acSAndroid Build Coastguard Worker ptpriv->io_loop = loop;
745*1c60b9acSAndroid Build Coastguard Worker uv_idle_init(loop, &ptpriv->idle);
746*1c60b9acSAndroid Build Coastguard Worker LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->idle, pt);
747*1c60b9acSAndroid Build Coastguard Worker uv_idle_start(&ptpriv->idle, lws_uv_idle);
748*1c60b9acSAndroid Build Coastguard Worker
749*1c60b9acSAndroid Build Coastguard Worker ns = LWS_ARRAY_SIZE(sigs);
750*1c60b9acSAndroid Build Coastguard Worker if (lws_check_opt(context->options,
751*1c60b9acSAndroid Build Coastguard Worker LWS_SERVER_OPTION_UV_NO_SIGSEGV_SIGFPE_SPIN))
752*1c60b9acSAndroid Build Coastguard Worker ns = 2;
753*1c60b9acSAndroid Build Coastguard Worker
754*1c60b9acSAndroid Build Coastguard Worker if (!pt->event_loop_foreign) {
755*1c60b9acSAndroid Build Coastguard Worker assert(ns <= (int)LWS_ARRAY_SIZE(ptpriv->signals));
756*1c60b9acSAndroid Build Coastguard Worker for (n = 0; n < ns; n++) {
757*1c60b9acSAndroid Build Coastguard Worker uv_signal_init(loop, &ptpriv->signals[n]);
758*1c60b9acSAndroid Build Coastguard Worker LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(
759*1c60b9acSAndroid Build Coastguard Worker &ptpriv->signals[n], pt);
760*1c60b9acSAndroid Build Coastguard Worker ptpriv->signals[n].data = pt;
761*1c60b9acSAndroid Build Coastguard Worker uv_signal_start(&ptpriv->signals[n],
762*1c60b9acSAndroid Build Coastguard Worker lws_uv_signal_handler, sigs[n]);
763*1c60b9acSAndroid Build Coastguard Worker }
764*1c60b9acSAndroid Build Coastguard Worker }
765*1c60b9acSAndroid Build Coastguard Worker } else
766*1c60b9acSAndroid Build Coastguard Worker first = 0;
767*1c60b9acSAndroid Build Coastguard Worker
768*1c60b9acSAndroid Build Coastguard Worker /*
769*1c60b9acSAndroid Build Coastguard Worker * Initialize the accept wsi read watcher with all the listening sockets
770*1c60b9acSAndroid Build Coastguard Worker * and register a callback for read operations
771*1c60b9acSAndroid Build Coastguard Worker *
772*1c60b9acSAndroid Build Coastguard Worker * We have to do it here because the uv loop(s) are not
773*1c60b9acSAndroid Build Coastguard Worker * initialized until after context creation.
774*1c60b9acSAndroid Build Coastguard Worker */
775*1c60b9acSAndroid Build Coastguard Worker lws_vhost_foreach_listen_wsi(context, context, elops_listen_init_uv);
776*1c60b9acSAndroid Build Coastguard Worker
777*1c60b9acSAndroid Build Coastguard Worker if (!first)
778*1c60b9acSAndroid Build Coastguard Worker return status;
779*1c60b9acSAndroid Build Coastguard Worker
780*1c60b9acSAndroid Build Coastguard Worker uv_timer_init(ptpriv->io_loop, &ptpriv->sultimer);
781*1c60b9acSAndroid Build Coastguard Worker LWS_UV_REFCOUNT_STATIC_HANDLE_NEW(&ptpriv->sultimer, pt);
782*1c60b9acSAndroid Build Coastguard Worker
783*1c60b9acSAndroid Build Coastguard Worker return status;
784*1c60b9acSAndroid Build Coastguard Worker }
785*1c60b9acSAndroid Build Coastguard Worker
786*1c60b9acSAndroid Build Coastguard Worker static void
lws_libuv_closewsi(uv_handle_t * handle)787*1c60b9acSAndroid Build Coastguard Worker lws_libuv_closewsi(uv_handle_t* handle)
788*1c60b9acSAndroid Build Coastguard Worker {
789*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi = (struct lws *)handle->data;
790*1c60b9acSAndroid Build Coastguard Worker struct lws_context *context = lws_get_context(wsi);
791*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
792*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt);
793*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
794*1c60b9acSAndroid Build Coastguard Worker int lspd = 0;
795*1c60b9acSAndroid Build Coastguard Worker #endif
796*1c60b9acSAndroid Build Coastguard Worker
797*1c60b9acSAndroid Build Coastguard Worker // lwsl_wsi_notice(wsi, "in");
798*1c60b9acSAndroid Build Coastguard Worker
799*1c60b9acSAndroid Build Coastguard Worker lws_context_lock(context, __func__);
800*1c60b9acSAndroid Build Coastguard Worker
801*1c60b9acSAndroid Build Coastguard Worker /*
802*1c60b9acSAndroid Build Coastguard Worker * We get called back here for every wsi that closes
803*1c60b9acSAndroid Build Coastguard Worker */
804*1c60b9acSAndroid Build Coastguard Worker
805*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
806*1c60b9acSAndroid Build Coastguard Worker if (wsi->role_ops && !strcmp(wsi->role_ops->name, "listen") &&
807*1c60b9acSAndroid Build Coastguard Worker wsi->a.context->deprecated) {
808*1c60b9acSAndroid Build Coastguard Worker lspd = 1;
809*1c60b9acSAndroid Build Coastguard Worker context->deprecation_pending_listen_close_count--;
810*1c60b9acSAndroid Build Coastguard Worker if (!context->deprecation_pending_listen_close_count)
811*1c60b9acSAndroid Build Coastguard Worker lspd = 2;
812*1c60b9acSAndroid Build Coastguard Worker }
813*1c60b9acSAndroid Build Coastguard Worker #endif
814*1c60b9acSAndroid Build Coastguard Worker
815*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
816*1c60b9acSAndroid Build Coastguard Worker
817*1c60b9acSAndroid Build Coastguard Worker lwsl_wsi_info(wsi, "thr %d: sa left %d: dyn left: %d (rk %d)",
818*1c60b9acSAndroid Build Coastguard Worker (int)(pt - &pt->context->pt[0]),
819*1c60b9acSAndroid Build Coastguard Worker pt->count_event_loop_static_asset_handles,
820*1c60b9acSAndroid Build Coastguard Worker ptpriv->extant_handles - 1,
821*1c60b9acSAndroid Build Coastguard Worker context->requested_stop_internal_loops);
822*1c60b9acSAndroid Build Coastguard Worker
823*1c60b9acSAndroid Build Coastguard Worker __lws_close_free_wsi_final(wsi);
824*1c60b9acSAndroid Build Coastguard Worker assert(ptpriv->extant_handles);
825*1c60b9acSAndroid Build Coastguard Worker ptpriv->extant_handles--;
826*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
827*1c60b9acSAndroid Build Coastguard Worker
828*1c60b9acSAndroid Build Coastguard Worker /* it's our job to close the handle finally */
829*1c60b9acSAndroid Build Coastguard Worker lws_free(handle);
830*1c60b9acSAndroid Build Coastguard Worker
831*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
832*1c60b9acSAndroid Build Coastguard Worker if (lspd == 2 && context->deprecation_cb) {
833*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_notice(context, "calling deprecation callback");
834*1c60b9acSAndroid Build Coastguard Worker context->deprecation_cb();
835*1c60b9acSAndroid Build Coastguard Worker }
836*1c60b9acSAndroid Build Coastguard Worker #endif
837*1c60b9acSAndroid Build Coastguard Worker
838*1c60b9acSAndroid Build Coastguard Worker /*
839*1c60b9acSAndroid Build Coastguard Worker * eventually, we closed all the wsi...
840*1c60b9acSAndroid Build Coastguard Worker */
841*1c60b9acSAndroid Build Coastguard Worker
842*1c60b9acSAndroid Build Coastguard Worker if (context->requested_stop_internal_loops &&
843*1c60b9acSAndroid Build Coastguard Worker !ptpriv->extant_handles &&
844*1c60b9acSAndroid Build Coastguard Worker !pt->count_event_loop_static_asset_handles) {
845*1c60b9acSAndroid Build Coastguard Worker
846*1c60b9acSAndroid Build Coastguard Worker /*
847*1c60b9acSAndroid Build Coastguard Worker * we closed everything on this pt
848*1c60b9acSAndroid Build Coastguard Worker */
849*1c60b9acSAndroid Build Coastguard Worker
850*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(context);
851*1c60b9acSAndroid Build Coastguard Worker lws_uv_finalize_pt(pt);
852*1c60b9acSAndroid Build Coastguard Worker
853*1c60b9acSAndroid Build Coastguard Worker return;
854*1c60b9acSAndroid Build Coastguard Worker }
855*1c60b9acSAndroid Build Coastguard Worker
856*1c60b9acSAndroid Build Coastguard Worker lws_context_unlock(context);
857*1c60b9acSAndroid Build Coastguard Worker }
858*1c60b9acSAndroid Build Coastguard Worker
859*1c60b9acSAndroid Build Coastguard Worker void
lws_libuv_closehandle(struct lws * wsi)860*1c60b9acSAndroid Build Coastguard Worker lws_libuv_closehandle(struct lws *wsi)
861*1c60b9acSAndroid Build Coastguard Worker {
862*1c60b9acSAndroid Build Coastguard Worker uv_handle_t* handle;
863*1c60b9acSAndroid Build Coastguard Worker struct lws_io_watcher_libuv *w_read = &wsi_to_priv_uv(wsi)->w_read;
864*1c60b9acSAndroid Build Coastguard Worker
865*1c60b9acSAndroid Build Coastguard Worker if (!w_read->pwatcher)
866*1c60b9acSAndroid Build Coastguard Worker return;
867*1c60b9acSAndroid Build Coastguard Worker
868*1c60b9acSAndroid Build Coastguard Worker if (wsi->told_event_loop_closed)
869*1c60b9acSAndroid Build Coastguard Worker return;
870*1c60b9acSAndroid Build Coastguard Worker
871*1c60b9acSAndroid Build Coastguard Worker // lwsl_wsi_debug(wsi, "in");
872*1c60b9acSAndroid Build Coastguard Worker
873*1c60b9acSAndroid Build Coastguard Worker wsi->told_event_loop_closed = 1;
874*1c60b9acSAndroid Build Coastguard Worker
875*1c60b9acSAndroid Build Coastguard Worker /*
876*1c60b9acSAndroid Build Coastguard Worker * The normal close path attaches the related wsi as the
877*1c60b9acSAndroid Build Coastguard Worker * handle->data.
878*1c60b9acSAndroid Build Coastguard Worker */
879*1c60b9acSAndroid Build Coastguard Worker
880*1c60b9acSAndroid Build Coastguard Worker handle = (uv_handle_t *)w_read->pwatcher;
881*1c60b9acSAndroid Build Coastguard Worker
882*1c60b9acSAndroid Build Coastguard Worker /* ensure we can only do this once */
883*1c60b9acSAndroid Build Coastguard Worker
884*1c60b9acSAndroid Build Coastguard Worker w_read->pwatcher = NULL;
885*1c60b9acSAndroid Build Coastguard Worker
886*1c60b9acSAndroid Build Coastguard Worker uv_close(handle, lws_libuv_closewsi);
887*1c60b9acSAndroid Build Coastguard Worker }
888*1c60b9acSAndroid Build Coastguard Worker
889*1c60b9acSAndroid Build Coastguard Worker static int
elops_foreign_thread_uv(struct lws_context * cx,int tsi)890*1c60b9acSAndroid Build Coastguard Worker elops_foreign_thread_uv(struct lws_context *cx, int tsi)
891*1c60b9acSAndroid Build Coastguard Worker {
892*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &cx->pt[tsi];
893*1c60b9acSAndroid Build Coastguard Worker struct lws_pt_eventlibs_libuv *ptpriv = pt_to_priv_uv(pt);
894*1c60b9acSAndroid Build Coastguard Worker uv_thread_t th = uv_thread_self();
895*1c60b9acSAndroid Build Coastguard Worker
896*1c60b9acSAndroid Build Coastguard Worker if (!ptpriv->thread_valid)
897*1c60b9acSAndroid Build Coastguard Worker /*
898*1c60b9acSAndroid Build Coastguard Worker * We can't judge it until we get the first event from the loop
899*1c60b9acSAndroid Build Coastguard Worker */
900*1c60b9acSAndroid Build Coastguard Worker return 0;
901*1c60b9acSAndroid Build Coastguard Worker
902*1c60b9acSAndroid Build Coastguard Worker /*
903*1c60b9acSAndroid Build Coastguard Worker * This is the same thread that gave us the first event on this loop?
904*1c60b9acSAndroid Build Coastguard Worker * Return 0 if so.
905*1c60b9acSAndroid Build Coastguard Worker */
906*1c60b9acSAndroid Build Coastguard Worker
907*1c60b9acSAndroid Build Coastguard Worker return !uv_thread_equal(&th, &ptpriv->uv_thread);
908*1c60b9acSAndroid Build Coastguard Worker }
909*1c60b9acSAndroid Build Coastguard Worker
910*1c60b9acSAndroid Build Coastguard Worker static const struct lws_event_loop_ops event_loop_ops_uv = {
911*1c60b9acSAndroid Build Coastguard Worker /* name */ "libuv",
912*1c60b9acSAndroid Build Coastguard Worker /* init_context */ elops_init_context_uv,
913*1c60b9acSAndroid Build Coastguard Worker /* destroy_context1 */ elops_destroy_context1_uv,
914*1c60b9acSAndroid Build Coastguard Worker /* destroy_context2 */ elops_destroy_context2_uv,
915*1c60b9acSAndroid Build Coastguard Worker /* init_vhost_listen_wsi */ elops_init_vhost_listen_wsi_uv,
916*1c60b9acSAndroid Build Coastguard Worker /* init_pt */ elops_init_pt_uv,
917*1c60b9acSAndroid Build Coastguard Worker /* wsi_logical_close */ elops_wsi_logical_close_uv,
918*1c60b9acSAndroid Build Coastguard Worker /* check_client_connect_ok */ elops_check_client_connect_ok_uv,
919*1c60b9acSAndroid Build Coastguard Worker /* close_handle_manually */ elops_close_handle_manually_uv,
920*1c60b9acSAndroid Build Coastguard Worker /* accept */ elops_accept_uv,
921*1c60b9acSAndroid Build Coastguard Worker /* io */ elops_io_uv,
922*1c60b9acSAndroid Build Coastguard Worker /* run_pt */ elops_run_pt_uv,
923*1c60b9acSAndroid Build Coastguard Worker /* destroy_pt */ elops_destroy_pt_uv,
924*1c60b9acSAndroid Build Coastguard Worker /* destroy wsi */ NULL,
925*1c60b9acSAndroid Build Coastguard Worker /* foreign_thread */ elops_foreign_thread_uv,
926*1c60b9acSAndroid Build Coastguard Worker
927*1c60b9acSAndroid Build Coastguard Worker /* flags */ 0,
928*1c60b9acSAndroid Build Coastguard Worker
929*1c60b9acSAndroid Build Coastguard Worker /* evlib_size_ctx */ sizeof(struct lws_context_eventlibs_libuv),
930*1c60b9acSAndroid Build Coastguard Worker /* evlib_size_pt */ sizeof(struct lws_pt_eventlibs_libuv),
931*1c60b9acSAndroid Build Coastguard Worker /* evlib_size_vh */ 0,
932*1c60b9acSAndroid Build Coastguard Worker /* evlib_size_wsi */ sizeof(struct lws_io_watcher_libuv),
933*1c60b9acSAndroid Build Coastguard Worker };
934*1c60b9acSAndroid Build Coastguard Worker
935*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_EVLIB_PLUGINS)
936*1c60b9acSAndroid Build Coastguard Worker LWS_VISIBLE
937*1c60b9acSAndroid Build Coastguard Worker #endif
938*1c60b9acSAndroid Build Coastguard Worker const lws_plugin_evlib_t evlib_uv = {
939*1c60b9acSAndroid Build Coastguard Worker .hdr = {
940*1c60b9acSAndroid Build Coastguard Worker "libuv event loop",
941*1c60b9acSAndroid Build Coastguard Worker "lws_evlib_plugin",
942*1c60b9acSAndroid Build Coastguard Worker LWS_BUILD_HASH,
943*1c60b9acSAndroid Build Coastguard Worker LWS_PLUGIN_API_MAGIC
944*1c60b9acSAndroid Build Coastguard Worker },
945*1c60b9acSAndroid Build Coastguard Worker
946*1c60b9acSAndroid Build Coastguard Worker .ops = &event_loop_ops_uv
947*1c60b9acSAndroid Build Coastguard Worker };
948*1c60b9acSAndroid Build Coastguard Worker
949