@@ -148,6 +148,9 @@ lws_io_cb(uv_poll_t *watcher, int status, int revents)
148148 lws_service_fd_tsi (context , & eventfd , wsi -> tsi );
149149
150150 if (pt -> destroy_self ) {
151+ lwsl_cx_notice (context , "%s: wsi %s: pt destroy_self -> "
152+ "context destroy" , __func__ ,
153+ lws_wsi_tag (wsi ));
151154 lws_context_destroy (pt -> context );
152155 return ;
153156 }
@@ -174,6 +177,9 @@ lws_libuv_stop(struct lws_context *context)
174177 return ;
175178 }
176179
180+ lwsl_cx_notice (context , "%s: initiating loop stop + context destroy" ,
181+ __func__ );
182+
177183 context -> requested_stop_internal_loops = 1 ;
178184 lws_context_destroy (context );
179185}
@@ -211,7 +217,8 @@ lws_uv_finalize_pt(struct lws_context_per_thread *pt)
211217 * eventually, we emptied all the pts...
212218 */
213219
214- lwsl_cx_debug (pt -> context , "all pts down now" );
220+ lwsl_cx_notice (pt -> context , "%s: last pt down, closing vhosts" ,
221+ __func__ );
215222
216223 /* protocols may have initialized libuv objects */
217224
@@ -222,7 +229,9 @@ lws_uv_finalize_pt(struct lws_context_per_thread *pt)
222229
223230 if (!pt -> count_event_loop_static_asset_handles &&
224231 pt -> event_loop_foreign ) {
225- lwsl_cx_info (pt -> context , "resuming context_destroy" );
232+ lwsl_cx_notice (pt -> context ,
233+ "%s: foreign loop, resuming context destroy" ,
234+ __func__ );
226235 lws_context_unlock (pt -> context );
227236 lws_context_destroy (pt -> context );
228237 /*
@@ -293,8 +302,13 @@ lws_uv_close_cb_sa(uv_handle_t *handle)
293302
294303 lwsl_cx_info (context , "thr %d: seen final static handle gone" , tsi );
295304
296- if (!pt -> event_loop_foreign )
305+ if (!pt -> event_loop_foreign ) {
306+ lwsl_cx_notice (context ,
307+ "%s: thr %d: all lws handles gone from "
308+ "internal loop, destroying context" ,
309+ __func__ , tsi );
297310 lws_context_destroy (context );
311+ }
298312
299313 lws_uv_finalize_pt (pt );
300314
@@ -329,8 +343,12 @@ lws_libuv_static_refcount_del(uv_handle_t *h)
329343void
330344lws_libuv_stop_without_kill (const struct lws_context * context , int tsi )
331345{
332- if (pt_to_priv_uv (& context -> pt [tsi ])-> io_loop )
346+ if (pt_to_priv_uv (& context -> pt [tsi ])-> io_loop ) {
347+ lwsl_cx_notice ((struct lws_context * )context ,
348+ "%s: tsi %d: stopping loop without "
349+ "context destroy" , __func__ , tsi );
333350 uv_stop (pt_to_priv_uv (& context -> pt [tsi ])-> io_loop );
351+ }
334352}
335353
336354uv_loop_t *
@@ -685,8 +703,26 @@ elops_init_vhost_listen_wsi_uv(struct lws *wsi)
685703static void
686704elops_run_pt_uv (struct lws_context * context , int tsi )
687705{
688- if (pt_to_priv_uv (& context -> pt [tsi ])-> io_loop )
689- uv_run (pt_to_priv_uv (& context -> pt [tsi ])-> io_loop , 0 );
706+ if (pt_to_priv_uv (& context -> pt [tsi ])-> io_loop ) {
707+ uv_loop_t * io_loop = pt_to_priv_uv (& context -> pt [tsi ])-> io_loop ;
708+
709+ uv_run (io_loop , 0 );
710+
711+ /*
712+ * This is the point the whole app falls out of its event
713+ * loop. If we get here unexpectedly, either something called
714+ * uv_stop() on the loop (loop still "alive"), or every handle
715+ * on the loop became inactive/closed. The initiation logs in
716+ * the destroy paths show who started that.
717+ */
718+ lwsl_cx_notice (context ,
719+ "%s: tsi %d: uv_run exited: loop alive %d, "
720+ "ctx being_destroyed %d, deprecated %d" ,
721+ __func__ , tsi ,
722+ uv_loop_alive (io_loop ),
723+ context -> being_destroyed ,
724+ lws_context_is_deprecated (context ));
725+ }
690726}
691727
692728static void
@@ -704,7 +740,8 @@ elops_destroy_pt_uv(struct lws_context *context, int tsi)
704740
705741 if (pt -> event_loop_destroy_processing_done ) {
706742 if (!pt -> event_loop_foreign ) {
707- lwsl_warn ("%s: stopping event loop\n" , __func__ );
743+ lwsl_cx_notice (context , "%s: thr %d: stopping event loop" ,
744+ __func__ , tsi );
708745 uv_stop (pt_to_priv_uv (pt )-> io_loop );
709746 }
710747 return ;
0 commit comments