int lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or) { if (!wsi || !wsi->protocol || wsi->position_in_fds_table < 0) return 1; struct libwebsocket_context *context = wsi->protocol->owning_server; if (!context) return 1; int tid; int sampled_tid; struct libwebsocket_pollfd *pfd; struct libwebsocket_pollargs pa; pfd = &context->fds[wsi->position_in_fds_table]; pa.fd = wsi->sock; context->protocols[0].callback(context, wsi, LWS_CALLBACK_LOCK_POLL, wsi->user_space, (void *) &pa, 0); pa.prev_events = pfd->events; pa.events = pfd->events = (pfd->events & ~_and) | _or; context->protocols[0].callback(context, wsi, LWS_CALLBACK_CHANGE_MODE_POLL_FD, wsi->user_space, (void *) &pa, 0); /* * if we changed something in this pollfd... * ... and we're running in a different thread context * than the service thread... * ... and the service thread is waiting ... * then cancel it to force a restart with our changed events */ if (pa.prev_events != pa.events) { if (lws_plat_change_pollfd(context, wsi, pfd)) { lwsl_info("%s failed\n", __func__); return 1; } sampled_tid = context->service_tid; if (sampled_tid) { tid = context->protocols[0].callback(context, NULL, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); if (tid != sampled_tid) libwebsocket_cancel_service(context); } } context->protocols[0].callback(context, wsi, LWS_CALLBACK_UNLOCK_POLL, wsi->user_space, (void *) &pa, 0); return 0; }
int _lws_change_pollfd(struct lws *wsi, int _and, int _or, struct lws_pollargs *pa) { struct lws_context_per_thread *pt; struct lws_context *context; int ret = 0, pa_events = 1; struct lws_pollfd *pfd; int sampled_tid, tid; if (!wsi || wsi->position_in_fds_table < 0) return 0; context = wsi->context; pt = &context->pt[(int)wsi->tsi]; assert(wsi->position_in_fds_table >= 0 && wsi->position_in_fds_table < pt->fds_count); pfd = &pt->fds[wsi->position_in_fds_table]; pa->fd = wsi->sock; pa->prev_events = pfd->events; pa->events = pfd->events = (pfd->events & ~_and) | _or; if (context->protocols[0].callback(wsi, LWS_CALLBACK_CHANGE_MODE_POLL_FD, wsi->user_space, (void *)pa, 0)) { ret = -1; goto bail; } /* * if we changed something in this pollfd... * ... and we're running in a different thread context * than the service thread... * ... and the service thread is waiting ... * then cancel it to force a restart with our changed events */ #if LWS_POSIX pa_events = pa->prev_events != pa->events; #endif if (pa_events) { if (lws_plat_change_pollfd(context, wsi, pfd)) { lwsl_info("%s failed\n", __func__); ret = -1; goto bail; } sampled_tid = context->service_tid; if (sampled_tid) { tid = context->protocols[0].callback(wsi, LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0); if (tid == -1) { ret = -1; goto bail; } if (tid != sampled_tid) lws_cancel_service_pt(wsi); } } bail: return ret; }