diff --git a/lib/client/client.c b/lib/client/client.c index a4eb7a6e..bd6ce27a 100644 --- a/lib/client/client.c +++ b/lib/client/client.c @@ -868,6 +868,9 @@ check_extensions: * X <-> B * X <-> pAn <-> pB */ + + lws_vhost_lock(wsi->vhost); + wsi->same_vh_protocol_prev = /* guy who points to us */ &wsi->vhost->same_vh_protocol_list[n]; wsi->same_vh_protocol_next = /* old first guy is our next */ @@ -880,6 +883,8 @@ check_extensions: wsi->same_vh_protocol_next->same_vh_protocol_prev = &wsi->same_vh_protocol_next; + lws_vhost_unlock(wsi->vhost); + #ifndef LWS_NO_EXTENSIONS /* instantiate the accepted extensions */ diff --git a/lib/context.c b/lib/context.c index f0cb8bab..6bd4a8bd 100644 --- a/lib/context.c +++ b/lib/context.c @@ -570,6 +570,10 @@ lws_create_vhost(struct lws_context *context, if (!vh) return NULL; +#if LWS_MAX_SMP > 1 + pthread_mutex_init(&vh->lock, NULL); +#endif + if (!info->protocols) info->protocols = &protocols_dummy[0]; @@ -1589,6 +1593,10 @@ lws_vhost_destroy2(struct lws_vhost *vh) lws_free_set_NULL(vh->alloc_cert_path); +#if LWS_MAX_SMP > 1 + pthread_mutex_destroy(&vh->lock); +#endif + /* * although async event callbacks may still come for wsi handles with * pending close in the case of asycn event library like libuv, diff --git a/lib/pollfd.c b/lib/pollfd.c index 8d63c468..c08f2086 100644 --- a/lib/pollfd.c +++ b/lib/pollfd.c @@ -532,6 +532,8 @@ lws_same_vh_protocol_insert(struct lws *wsi, int n) lwsl_notice("Attempted to attach wsi twice to same vh prot\n"); } + lws_vhost_lock(wsi->vhost); + wsi->same_vh_protocol_prev = &wsi->vhost->same_vh_protocol_list[n]; /* old first guy is our next */ wsi->same_vh_protocol_next = wsi->vhost->same_vh_protocol_list[n]; @@ -542,6 +544,8 @@ lws_same_vh_protocol_insert(struct lws *wsi, int n) /* old first guy points back to us now */ wsi->same_vh_protocol_next->same_vh_protocol_prev = &wsi->same_vh_protocol_next; + + lws_vhost_unlock(wsi->vhost); } void @@ -556,6 +560,11 @@ lws_same_vh_protocol_remove(struct lws *wsi) */ lwsl_info("%s: removing same prot wsi %p\n", __func__, wsi); + if (!wsi->vhost) + return; + + lws_vhost_lock(wsi->vhost); + if (wsi->same_vh_protocol_prev) { assert (*(wsi->same_vh_protocol_prev) == wsi); lwsl_info("have prev %p, setting him to our next %p\n", @@ -574,6 +583,8 @@ lws_same_vh_protocol_remove(struct lws *wsi) wsi->same_vh_protocol_prev = NULL; wsi->same_vh_protocol_next = NULL; + + lws_vhost_unlock(wsi->vhost); } diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h index 5b915793..da5c15a7 100644 --- a/lib/private-libwebsockets.h +++ b/lib/private-libwebsockets.h @@ -928,6 +928,9 @@ struct lws_tls_ss_pieces; struct lws_vhost { char http_proxy_address[128]; char proxy_basic_auth_token[128]; +#if LWS_MAX_SMP > 1 + pthread_mutex_t lock; +#endif #if defined(LWS_WITH_HTTP2) struct http2_settings set; #endif @@ -2480,6 +2483,19 @@ lws_context_unlock(struct lws_context *context) pthread_mutex_unlock(&context->lock); } +static LWS_INLINE void +lws_vhost_lock(struct lws_vhost *vhost) +{ + pthread_mutex_lock(&vhost->lock); +} + +static LWS_INLINE void +lws_vhost_unlock(struct lws_vhost *vhost) +{ + pthread_mutex_unlock(&vhost->lock); +} + + #else #define lws_pt_mutex_init(_a) (void)(_a) #define lws_pt_mutex_destroy(_a) (void)(_a) @@ -2487,6 +2503,8 @@ lws_context_unlock(struct lws_context *context) #define lws_pt_unlock(_a) (void)(_a) #define lws_context_lock(_a) (void)(_a) #define lws_context_unlock(_a) (void)(_a) +#define lws_vhost_lock(_a) (void)(_a) +#define lws_vhost_unlock(_a) (void)(_a) #endif LWS_EXTERN int LWS_WARN_UNUSED_RESULT diff --git a/lib/service.c b/lib/service.c index 627b90d0..034d94d4 100644 --- a/lib/service.c +++ b/lib/service.c @@ -1281,6 +1281,9 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, context->last_ws_ping_pong_check_s = now; while (vh) { + + lws_vhost_lock(vh); + for (n = 0; n < vh->count_protocols; n++) { wsi = vh->same_vh_protocol_list[n]; @@ -1306,6 +1309,9 @@ lws_service_fd_tsi(struct lws_context *context, struct lws_pollfd *pollfd, wsi = wsi->same_vh_protocol_next; } } + + lws_vhost_unlock(vh); + vh = vh->vhost_next; } }