client: add libuv support to lws_client_reset

More direct solution to problem described in

https://github.com/warmcat/libwebsockets/pull/940
This commit is contained in:
Andy Green 2017-06-23 10:27:52 +08:00
parent abc2a5cd2e
commit ede9ad2b13
3 changed files with 56 additions and 1 deletions

View file

@ -203,6 +203,15 @@ lws_client_connect_2(struct lws *wsi)
if (!lws_socket_is_valid(wsi->desc.sockfd)) {
#if defined(LWS_USE_LIBUV)
if (LWS_LIBUV_ENABLED(context))
if (lws_libuv_check_watcher_active(wsi)) {
lwsl_warn("Waiting for libuv watcher to close\n");
cce = "waiting for libuv watcher to close";
goto oom4;
}
#endif
#ifdef LWS_USE_IPV6
if (wsi->ipv6) {
sa46.sa6.sin6_port = htons(port);
@ -232,6 +241,7 @@ lws_client_connect_2(struct lws *wsi)
lws_libev_accept(wsi, wsi->desc);
lws_libuv_accept(wsi, wsi->desc);
lws_libevent_accept(wsi, wsi->desc);
if (insert_wsi_socket_into_fds(context, wsi)) {
compatible_close(wsi->desc.sockfd);
cce = "insert wsi failed";
@ -474,7 +484,22 @@ lws_client_reset(struct lws **pwsi, int ssl, const char *address, int port,
/* close the connection by hand */
#ifdef LWS_USE_LIBUV
if (LWS_LIBUV_ENABLED(wsi->context)) {
lwsl_debug("%s: lws_libuv_closehandle: wsi %p\n", __func__, wsi);
/*
* libuv has to do his own close handle processing asynchronously
* but once it starts we can do everything else synchronously,
* including trash wsi->desc.sockfd since it took a copy.
*
* When it completes it will call compatible_close()
*/
lws_libuv_closehandle_manually(wsi);
} else
#else
compatible_close(wsi->desc.sockfd);
#endif
remove_wsi_socket_from_fds(wsi);
wsi->desc.sockfd = LWS_SOCK_INVALID;

View file

@ -520,13 +520,39 @@ lws_libuv_closehandle(struct lws *wsi)
struct lws_context *context = lws_get_context(wsi);
/* required to defer actual deletion until libuv has processed it */
uv_close((uv_handle_t*)&wsi->w_read.uv_watcher, lws_libuv_closewsi);
if (context->requested_kill && context->count_wsi_allocated == 0)
lws_libuv_kill(context);
}
static void
lws_libuv_closewsi_m(uv_handle_t* handle)
{
lws_sockfd_type sockfd = (lws_sockfd_type)(long long)handle->data;
compatible_close(sockfd);
}
void
lws_libuv_closehandle_manually(struct lws *wsi)
{
uv_handle_t *h = (void *)&wsi->w_read.uv_watcher;
h->data = (void *)(long long)wsi->desc.sockfd;
/* required to defer actual deletion until libuv has processed it */
uv_close((uv_handle_t*)&wsi->w_read.uv_watcher, lws_libuv_closewsi_m);
}
int
lws_libuv_check_watcher_active(struct lws *wsi)
{
uv_handle_t *h = (void *)&wsi->w_read.uv_watcher;
return uv_is_active(h);
}
#if defined(LWS_WITH_PLUGINS) && (UV_VERSION_MAJOR > 0)
LWS_VISIBLE int

View file

@ -1035,6 +1035,10 @@ LWS_EXTERN void
lws_close_free_wsi_final(struct lws *wsi);
LWS_EXTERN void
lws_libuv_closehandle(struct lws *wsi);
LWS_EXTERN void
lws_libuv_closehandle_manually(struct lws *wsi);
LWS_EXTERN int
lws_libuv_check_watcher_active(struct lws *wsi);
LWS_VISIBLE LWS_EXTERN int
lws_plat_plugins_init(struct lws_context * context, const char * const *d);