1
0
Fork 0
mirror of https://github.com/warmcat/libwebsockets.git synced 2025-03-09 00:00:04 +01:00

libuv: context creation fails via destroy

When using a foreign libuv loop, context creation may fail after adding
handles to the foreign loop... if so, it can no longer deal with the
fatal error by unpicking the created context and returning NULL... it
has to brazen it out with a half-baked context that has already started
the destroy flow and allow the foreign loop to close out the handles
the usual way for libuv.

https://github.com/warmcat/libwebsockets/issues/2129
This commit is contained in:
Andy Green 2020-11-28 05:41:26 +00:00
parent 8f68bc1fc8
commit b3ddd3db17

View file

@ -401,6 +401,9 @@ lws_create_context(const struct lws_context_creation_info *info)
struct lws_plugin *evlib_plugin_list = NULL;
char *ld_env;
#endif
#if defined(LWS_WITH_LIBUV)
char fatal_exit_defer = 0;
#endif
if (lpf) {
lpf+= 2;
@ -526,6 +529,11 @@ lws_create_context(const struct lws_context_creation_info *info)
goto bail;
}
#if defined(LWS_WITH_LIBUV)
if (!n) /* libuv */
fatal_exit_defer = !!info->foreign_loops;
#endif
if (!evlib_plugin_list) {
lwsl_err("%s: unable to load evlib plugin %s\n",
__func__, map[n].name);
@ -554,6 +562,7 @@ lws_create_context(const struct lws_context_creation_info *info)
if (lws_check_opt(info->options, LWS_SERVER_OPTION_LIBUV)) {
extern const lws_plugin_evlib_t evlib_uv;
plev = &evlib_uv;
fatal_exit_defer = !!info->foreign_loops;
}
#endif
@ -766,7 +775,7 @@ lws_create_context(const struct lws_context_creation_info *info)
if (n == -1) {
lwsl_err("Get RLIMIT_NOFILE failed!\n");
return NULL;
goto free_context_fail;
}
context->max_fds = rt.rlim_cur;
#else
@ -790,7 +799,7 @@ lws_create_context(const struct lws_context_creation_info *info)
lwsl_err("%s: problem getting process max files\n",
__func__);
return NULL;
goto free_context_fail;
}
#endif
@ -1023,13 +1032,19 @@ lws_create_context(const struct lws_context_creation_info *info)
context->fd_limit_per_thread;
#endif
/*
* Past here, we may have added handles to the event lib
* loop and if libuv, have to take care about how to unpick them...
*/
if (lws_plat_init(context, info))
goto bail;
goto bail_libuv_aware;
#if defined(LWS_WITH_NETWORK)
if (context->event_loop_ops->init_context)
if (context->event_loop_ops->init_context(context, info))
goto bail;
goto bail_libuv_aware;
if (context->event_loop_ops->init_pt)
@ -1040,11 +1055,11 @@ lws_create_context(const struct lws_context_creation_info *info)
lp = info->foreign_loops[n];
if (context->event_loop_ops->init_pt(context, lp, n))
goto bail;
goto bail_libuv_aware;
}
if (lws_create_event_pipes(context))
goto bail;
goto bail_libuv_aware;
for (n = 0; n < context->count_threads; n++) {
LWS_FOR_EVERY_AVAILABLE_ROLE_START(ar) {
@ -1126,18 +1141,18 @@ lws_create_context(const struct lws_context_creation_info *info)
if (!vh) {
lwsl_err("%s: failed to create system vhost\n",
__func__);
goto bail;
goto bail_libuv_aware;
}
context->vhost_system = vh;
if (lws_protocol_init_vhost(vh, NULL)) {
lwsl_err("%s: failed to init system vhost\n", __func__);
goto bail;
goto bail_libuv_aware;
}
#if defined(LWS_WITH_SYS_ASYNC_DNS)
if (lws_async_dns_init(context))
goto bail;
goto bail_libuv_aware;
#endif
}
@ -1198,17 +1213,17 @@ lws_create_context(const struct lws_context_creation_info *info)
LWS_SERVER_OPTION_EXPLICIT_VHOSTS));
if (lws_ss_policy_parse_begin(context, 0))
goto bail;
goto bail_libuv_aware;
n = lws_ss_policy_parse(context,
(uint8_t *)context->pss_policies_json,
strlen(context->pss_policies_json));
if (n != LEJP_CONTINUE && n < 0)
goto bail;
goto bail_libuv_aware;
if (lws_ss_policy_set(context, "hardcoded")) {
lwsl_err("%s: policy set failed\n", __func__);
goto bail;
goto bail_libuv_aware;
}
} else
#else
@ -1217,7 +1232,7 @@ lws_create_context(const struct lws_context_creation_info *info)
if (lws_ss_policy_set(context, "hardcoded")) {
lwsl_err("%s: policy set failed\n", __func__);
goto bail;
goto bail_libuv_aware;
}
} //else
#endif
@ -1236,7 +1251,7 @@ lws_create_context(const struct lws_context_creation_info *info)
*/
if (!lws_check_opt(info->options, LWS_SERVER_OPTION_EXPLICIT_VHOSTS))
if (lws_plat_drop_app_privileges(context, 1))
goto bail;
goto bail_libuv_aware;
#if defined(LWS_WITH_SYS_STATE)
/*
@ -1260,6 +1275,14 @@ lws_create_context(const struct lws_context_creation_info *info)
#if defined(LWS_WITH_NETWORK)
fail_clean_pipes:
#if defined(LWS_WITH_LIBUV)
if (fatal_exit_defer) {
lws_context_destroy(context);
return context;
}
#endif
for (n = 0; n < context->count_threads; n++)
lws_destroy_event_pipe(context->pt[n].pipe_wsi);
@ -1275,9 +1298,18 @@ bail:
return NULL;
bail_libuv_aware:
lws_context_destroy(context);
#if defined(LWS_WITH_LIBUV)
return fatal_exit_defer ? context : NULL;
#else
return NULL;
#endif
fail_event_libs:
lwsl_err("Requested event library support not configured\n");
free_context_fail:
lws_free(context);
return NULL;