Skip to content
Snippets Groups Projects
Commit 9cce1874 authored by Andy Green's avatar Andy Green
Browse files

context_destroy: figure out if anything still in event loop

parent bce8cca0
No related branches found
No related tags found
No related merge requests found
...@@ -1721,6 +1721,10 @@ lws_vhost_destroy(struct lws_vhost *vh) ...@@ -1721,6 +1721,10 @@ lws_vhost_destroy(struct lws_vhost *vh)
* destroys the context itself, setting what was info.pcontext to NULL. * destroys the context itself, setting what was info.pcontext to NULL.
*/ */
/*
* destroy the actual context itself
*/
static void static void
lws_context_destroy3(struct lws_context *context) lws_context_destroy3(struct lws_context *context)
{ {
...@@ -1733,6 +1737,10 @@ lws_context_destroy3(struct lws_context *context) ...@@ -1733,6 +1737,10 @@ lws_context_destroy3(struct lws_context *context)
*pcontext_finalize = NULL; *pcontext_finalize = NULL;
} }
/*
* really start destroying things
*/
void void
lws_context_destroy2(struct lws_context *context) lws_context_destroy2(struct lws_context *context)
{ {
...@@ -1802,6 +1810,10 @@ lws_context_destroy2(struct lws_context *context) ...@@ -1802,6 +1810,10 @@ lws_context_destroy2(struct lws_context *context)
lws_context_destroy3(context); lws_context_destroy3(context);
} }
/*
* Begin the context takedown
*/
LWS_VISIBLE void LWS_VISIBLE void
lws_context_destroy(struct lws_context *context) lws_context_destroy(struct lws_context *context)
{ {
...@@ -1909,6 +1921,22 @@ lws_context_destroy(struct lws_context *context) ...@@ -1909,6 +1921,22 @@ lws_context_destroy(struct lws_context *context)
lws_plat_context_early_destroy(context); lws_plat_context_early_destroy(context);
/*
* We face two different needs depending if foreign loop or not.
*
* 1) If foreign loop, we really want to advance the destroy_context()
* past here, and block only for libuv-style async close completion.
*
* 2a) If poll, and we exited by ourselves and are calling a final
* destroy_context() outside of any service already, we want to
* advance all the way in one step.
*
* 2b) If poll, and we are reacting to a SIGINT, service thread(s) may
* be in poll wait or servicing. We can't advance the
* destroy_context() to the point it's freeing things; we have to
* leave that for the final destroy_context() after the service
* thread(s) are finished calling for service.
*/
if (context->event_loop_ops->destroy_context1) { if (context->event_loop_ops->destroy_context1) {
context->event_loop_ops->destroy_context1(context); context->event_loop_ops->destroy_context1(context);
...@@ -1916,5 +1944,10 @@ lws_context_destroy(struct lws_context *context) ...@@ -1916,5 +1944,10 @@ lws_context_destroy(struct lws_context *context)
return; return;
} }
if (!context->pt[0].event_loop_foreign)
for (n = 0; n < context->count_threads; n++)
if (context->pt[n].inside_service)
return;
lws_context_destroy2(context); lws_context_destroy2(context);
} }
...@@ -593,6 +593,7 @@ struct lws_context_per_thread { ...@@ -593,6 +593,7 @@ struct lws_context_per_thread {
unsigned char tid; unsigned char tid;
unsigned char lock_depth; unsigned char lock_depth;
unsigned char inside_service:1;
unsigned char event_loop_foreign:1; unsigned char event_loop_foreign:1;
unsigned char event_loop_destroy_processing_done:1; unsigned char event_loop_destroy_processing_done:1;
}; };
......
...@@ -939,24 +939,49 @@ lws_service_fd(struct lws_context *context, struct lws_pollfd *pollfd) ...@@ -939,24 +939,49 @@ lws_service_fd(struct lws_context *context, struct lws_pollfd *pollfd)
LWS_VISIBLE int LWS_VISIBLE int
lws_service(struct lws_context *context, int timeout_ms) lws_service(struct lws_context *context, int timeout_ms)
{ {
struct lws_context_per_thread *pt = &context->pt[0];
int n;
if (!context)
return 1;
pt->inside_service = 1;
if (context->event_loop_ops->run_pt) { if (context->event_loop_ops->run_pt) {
/* we are configured for an event loop */ /* we are configured for an event loop */
context->event_loop_ops->run_pt(context, 0); context->event_loop_ops->run_pt(context, 0);
pt->inside_service = 0;
return 1; return 1;
} }
return lws_plat_service(context, timeout_ms); n = lws_plat_service(context, timeout_ms);
pt->inside_service = 0;
return n;
} }
LWS_VISIBLE int LWS_VISIBLE int
lws_service_tsi(struct lws_context *context, int timeout_ms, int tsi) lws_service_tsi(struct lws_context *context, int timeout_ms, int tsi)
{ {
struct lws_context_per_thread *pt = &context->pt[tsi];
int n;
pt->inside_service = 1;
if (context->event_loop_ops->run_pt) { if (context->event_loop_ops->run_pt) {
/* we are configured for an event loop */ /* we are configured for an event loop */
context->event_loop_ops->run_pt(context, tsi); context->event_loop_ops->run_pt(context, tsi);
pt->inside_service = 0;
return 1; return 1;
} }
return _lws_plat_service_tsi(context, timeout_ms, tsi); n = _lws_plat_service_tsi(context, timeout_ms, tsi);
pt->inside_service = 0;
return n;
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment