mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
Use ppoll to allow signals to wake service loop early on change of pollfd event
To enable this code you need to force LWS_HAS_PPOLL to de defined. #defining it at the top of libwebsockets.c is enough. Signed-off-by: Andy Green <andy.green@linaro.org>
This commit is contained in:
parent
91f19d8d79
commit
3b3fa9e208
4 changed files with 88 additions and 2 deletions
|
@ -37,6 +37,8 @@
|
|||
#include <netdb.h>
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef LWS_OPENSSL_SUPPORT
|
||||
int openssl_websocket_private_data_index;
|
||||
#endif
|
||||
|
@ -83,6 +85,17 @@ static const char * const log_level_names[] = {
|
|||
struct libwebsocket *wsi, struct pollfd *pollfd);
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef LWS_HAS_PPOLL
|
||||
/*
|
||||
* set to the Thread ID that's doing the service loop just before entry to ppoll
|
||||
* indicates service thread likely idling in ppoll()
|
||||
* volatile because other threads may check it as part of processing for pollfd
|
||||
* event change.
|
||||
*/
|
||||
static volatile int lws_idling_ppoll_tid;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* lws_get_library_version: get version and git hash library built from
|
||||
*
|
||||
|
@ -1325,15 +1338,32 @@ libwebsocket_service(struct libwebsocket_context *context, int timeout_ms)
|
|||
{
|
||||
int n;
|
||||
int m;
|
||||
#ifdef LWS_HAS_PPOLL
|
||||
struct timespec timeout_ts;
|
||||
sigset_t sigmask;
|
||||
#endif
|
||||
|
||||
/* stay dead once we are dead */
|
||||
|
||||
if (context == NULL)
|
||||
return 1;
|
||||
|
||||
#ifdef LWS_HAS_PPOLL
|
||||
lws_idling_ppoll_tid = context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
|
||||
|
||||
timeout_ts.tv_sec = timeout_ms / 1000;
|
||||
timeout_ts.tv_nsec = timeout_ms % 1000;
|
||||
sigemptyset(&sigmask);
|
||||
sigaddset(&sigmask, SIGUSR2);
|
||||
|
||||
/* wait for something to need service */
|
||||
|
||||
n = ppoll(context->fds, context->fds_count, &timeout_ts, &sigmask);
|
||||
lws_idling_ppoll_tid = 0;
|
||||
#else
|
||||
n = poll(context->fds, context->fds_count, timeout_ms);
|
||||
#endif
|
||||
if (n == 0) /* poll timeout */ {
|
||||
libwebsocket_service_fd(context, NULL);
|
||||
return 0;
|
||||
|
@ -1408,13 +1438,19 @@ void
|
|||
lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or)
|
||||
{
|
||||
struct libwebsocket_context *context = wsi->protocol->owning_server;
|
||||
int events;
|
||||
#ifdef LWS_HAS_PPOLL
|
||||
int tid;
|
||||
int sampled_ppoll_tid;
|
||||
#endif
|
||||
|
||||
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 &= ~_and;
|
||||
context->fds[wsi->position_in_fds_table].events |= _or;
|
||||
events = context->fds[wsi->position_in_fds_table].events;
|
||||
|
||||
context->fds[wsi->position_in_fds_table].events = (events & ~_and) | _or;
|
||||
|
||||
/* external POLL support via protocol 0 */
|
||||
if (_and)
|
||||
|
@ -1427,6 +1463,26 @@ lws_change_pollfd(struct libwebsocket *wsi, int _and, int _or)
|
|||
LWS_CALLBACK_SET_MODE_POLL_FD,
|
||||
wsi->user_space, (void *)(long)wsi->sock, _or);
|
||||
|
||||
#ifdef LWS_HAS_PPOLL
|
||||
/*
|
||||
* 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 in ppoll()...
|
||||
* then fire a SIGUSR2 at the service thread to force it to
|
||||
* restart the ppoll() with our changed events
|
||||
*/
|
||||
if (events != context->fds[wsi->position_in_fds_table].events) {
|
||||
sampled_ppoll_tid = lws_idling_ppoll_tid;
|
||||
if (sampled_ppoll_tid) {
|
||||
tid = context->protocols[0].callback(context, NULL,
|
||||
LWS_CALLBACK_GET_THREAD_ID, NULL, NULL, 0);
|
||||
if (tid != sampled_ppoll_tid)
|
||||
kill(sampled_ppoll_tid, SIGUSR2);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
context->protocols[0].callback(context, wsi,
|
||||
LWS_CALLBACK_UNLOCK_POLL,
|
||||
wsi->user_space, (void *)(long)wsi->sock, 0);
|
||||
|
@ -1747,6 +1803,13 @@ int user_callback_handle_rxflow(callback_function callback_function,
|
|||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is just used to interrupt poll waiting
|
||||
* we don't have to do anything with it.
|
||||
*/
|
||||
static void lws_sigusr2(int sig)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* libwebsocket_create_context() - Create the websocket handler
|
||||
|
@ -2036,6 +2099,8 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
goto bail;
|
||||
}
|
||||
|
||||
signal(SIGUSR2, lws_sigusr2);
|
||||
|
||||
#ifdef SSL_OP_NO_COMPRESSION
|
||||
SSL_CTX_set_options(context->ssl_ctx, SSL_OP_NO_COMPRESSION);
|
||||
#endif
|
||||
|
@ -2349,6 +2414,7 @@ libwebsocket_create_context(struct lws_context_creation_info *info)
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return context;
|
||||
|
||||
bail:
|
||||
|
|
|
@ -63,6 +63,9 @@ typedef SSIZE_T ssize_t;
|
|||
#endif
|
||||
|
||||
#else // NOT WIN32
|
||||
|
||||
/* to get ppoll() */
|
||||
#define __USE_GNU
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
|
||||
|
@ -169,6 +172,8 @@ enum libwebsocket_callback_reasons {
|
|||
LWS_CALLBACK_CLIENT_CONFIRM_EXTENSION_SUPPORTED,
|
||||
LWS_CALLBACK_PROTOCOL_INIT,
|
||||
LWS_CALLBACK_PROTOCOL_DESTROY,
|
||||
LWS_CALLBACK_GET_THREAD_ID,
|
||||
|
||||
/* external poll() management support */
|
||||
LWS_CALLBACK_ADD_POLL_FD,
|
||||
LWS_CALLBACK_DEL_POLL_FD,
|
||||
|
|
|
@ -93,6 +93,8 @@
|
|||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
/* to get ppoll() */
|
||||
#define __USE_GNU
|
||||
#include <poll.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/time.h>
|
||||
|
|
|
@ -474,6 +474,19 @@ bail:
|
|||
break;
|
||||
#endif
|
||||
|
||||
case LWS_CALLBACK_GET_THREAD_ID:
|
||||
/*
|
||||
* if you will call "libwebsocket_callback_on_writable"
|
||||
* from a different thread, return the caller thread ID
|
||||
* here so lws can use this information to work out if it
|
||||
* should signal the ppoll() loop to exit and restart early
|
||||
* (only applies if the library has LWS_HAS_PPOLL
|
||||
*/
|
||||
|
||||
/* return pthread_getthreadid_np(); */
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue