add locking callback for fds
This adds two new callbacks in protocols[0] that are optional for allowing limited thread
access to libwebsockets, LWS_CALLBACK_LOCK_POLL and LWS_CALLBACK_UNLOCK_POLL.
If you use them, they protect internal and external poll list changes, but if you want to use
external thread access to libwebsocket_callback_on_writable() you have to implement your
locking here even if you don't use external poll support.
If you will use another thread for this, take a lot of care about managing your list of
live wsi by doing it from ESTABLISHED and CLOSED callbacks (with your own locking).
Signed-off-by: Andy Green <andy.green@linaro.org>
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index 8b2fec5..5562573 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -118,6 +118,10 @@
lwsl_info("insert_wsi_socket_into_fds: wsi=%p, sock=%d, fds pos=%d\n",
wsi, wsi->sock, context->fds_count);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
context->lws_lookup[wsi->sock] = wsi;
wsi->position_in_fds_table = context->fds_count;
context->fds[context->fds_count].fd = wsi->sock;
@@ -129,6 +133,10 @@
LWS_CALLBACK_ADD_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLIN);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
return 0;
}
@@ -138,8 +146,12 @@
{
int m;
- if (!--context->fds_count)
+ if (!--context->fds_count) {
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
goto do_ext;
+ }
if (wsi->sock > context->max_fds) {
lwsl_err("Socket fd %d too high (%d)\n",
@@ -150,6 +162,10 @@
lwsl_info("remove_wsi_socket_from_fds: wsi=%p, sock=%d, fds pos=%d\n",
wsi, wsi->sock, wsi->position_in_fds_table);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
m = wsi->position_in_fds_table; /* replace the contents for this */
/* have the last guy take up the vacant slot */
@@ -173,6 +189,10 @@
LWS_CALLBACK_DEL_POLL_FD, wsi->user_space,
(void *)(long)wsi->sock, 0);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
return 0;
}
@@ -789,12 +809,21 @@
/* one shot */
if (pollfd) {
+
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
pollfd->events &= ~POLLOUT;
/* external POLL support via protocol 0 */
context->protocols[0].callback(context, wsi,
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
+
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
}
#ifndef LWS_NO_EXTENSIONS
notify_action:
@@ -1427,6 +1456,10 @@
return -1;
}
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
context->fds[wsi->position_in_fds_table].events |= POLLOUT;
/* external POLL support via protocol 0 */
@@ -1434,6 +1467,10 @@
LWS_CALLBACK_SET_MODE_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLOUT);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
return 1;
}
@@ -1578,6 +1615,10 @@
/* adjust the pollfd for this wsi */
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_LOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
if (wsi->u.ws.rxflow_change_to & LWS_RXFLOW_ALLOW)
context->fds[wsi->position_in_fds_table].events |= POLLIN;
else
@@ -1594,6 +1635,10 @@
LWS_CALLBACK_CLEAR_MODE_POLL_FD,
wsi->user_space, (void *)(long)wsi->sock, POLLIN);
+ context->protocols[0].callback(context, wsi,
+ LWS_CALLBACK_UNLOCK_POLL,
+ wsi->user_space, (void *)(long)wsi->sock, 0);
+
return 1;
}
#endif