|
|
|
@ -661,10 +661,9 @@ void* uasync_add_socket(struct UASYNC* ua, int fd, socket_callback_t read_cbk, s |
|
|
|
if (read_cbk) ev.events |= EPOLLIN; |
|
|
|
if (read_cbk) ev.events |= EPOLLIN; |
|
|
|
if (write_cbk) ev.events |= EPOLLOUT; |
|
|
|
if (write_cbk) ev.events |= EPOLLOUT; |
|
|
|
// Use level-triggered mode (default) for compatibility with UDP sockets
|
|
|
|
// Use level-triggered mode (default) for compatibility with UDP sockets
|
|
|
|
ev.data.ptr = &ua->sockets->sockets[index]; |
|
|
|
ev.data.fd = fd; |
|
|
|
|
|
|
|
|
|
|
|
if (epoll_ctl(ua->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { |
|
|
|
if (epoll_ctl(ua->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { |
|
|
|
// Failed to add to epoll - remove from socket array and return error
|
|
|
|
|
|
|
|
socket_array_remove(ua->sockets, fd); |
|
|
|
socket_array_remove(ua->sockets, fd); |
|
|
|
ua->socket_alloc_count--; |
|
|
|
ua->socket_alloc_count--; |
|
|
|
return NULL; |
|
|
|
return NULL; |
|
|
|
@ -672,17 +671,15 @@ void* uasync_add_socket(struct UASYNC* ua, int fd, socket_callback_t read_cbk, s |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// Return pointer to the socket node as ID
|
|
|
|
return (void*)(intptr_t)fd; |
|
|
|
return &ua->sockets->sockets[index]; |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
err_t uasync_remove_socket(struct UASYNC* ua, void* s_id) { |
|
|
|
err_t uasync_remove_socket(struct UASYNC* ua, void* s_id) { |
|
|
|
if (!ua || !s_id) return ERR_FAIL; |
|
|
|
if (!ua || !s_id) return ERR_FAIL; |
|
|
|
|
|
|
|
|
|
|
|
struct socket_node* node = (struct socket_node*)s_id; |
|
|
|
int fd = (int)(intptr_t)s_id; |
|
|
|
if (!node->active || node->fd < 0) return ERR_FAIL; |
|
|
|
struct socket_node* node = socket_array_get(ua->sockets, fd); |
|
|
|
|
|
|
|
if (!node || !node->active) return ERR_FAIL; |
|
|
|
int fd = node->fd; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#if HAS_EPOLL |
|
|
|
#if HAS_EPOLL |
|
|
|
// Remove from epoll if using epoll
|
|
|
|
// Remove from epoll if using epoll
|
|
|
|
@ -712,20 +709,19 @@ void* uasync_add_socket_t(struct UASYNC* ua, socket_t sock, socket_t_callback_t |
|
|
|
ua->socket_alloc_count++; |
|
|
|
ua->socket_alloc_count++; |
|
|
|
ua->poll_fds_dirty = 1; |
|
|
|
ua->poll_fds_dirty = 1; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
int fd = (int)(intptr_t)sock; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
int fd = sock; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
#if HAS_EPOLL |
|
|
|
#if HAS_EPOLL |
|
|
|
if (ua->use_epoll && ua->epoll_fd >= 0) { |
|
|
|
if (ua->use_epoll && ua->epoll_fd >= 0) { |
|
|
|
struct epoll_event ev; |
|
|
|
struct epoll_event ev; |
|
|
|
ev.events = 0; |
|
|
|
ev.events = 0; |
|
|
|
if (read_cbk) ev.events |= EPOLLIN; |
|
|
|
if (read_cbk) ev.events |= EPOLLIN; |
|
|
|
if (write_cbk) ev.events |= EPOLLOUT; |
|
|
|
if (write_cbk) ev.events |= EPOLLOUT; |
|
|
|
ev.data.ptr = &ua->sockets->sockets[index]; |
|
|
|
ev.data.fd = fd; |
|
|
|
|
|
|
|
|
|
|
|
// On Windows, need to cast socket_t to int for epoll_ctl
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
|
|
|
int fd = (int)(intptr_t)sock; |
|
|
|
|
|
|
|
#else |
|
|
|
|
|
|
|
int fd = sock; |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
if (epoll_ctl(ua->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { |
|
|
|
if (epoll_ctl(ua->epoll_fd, EPOLL_CTL_ADD, fd, &ev) < 0) { |
|
|
|
socket_array_remove(ua->sockets, fd); |
|
|
|
socket_array_remove(ua->sockets, fd); |
|
|
|
ua->socket_alloc_count--; |
|
|
|
ua->socket_alloc_count--; |
|
|
|
@ -734,7 +730,7 @@ void* uasync_add_socket_t(struct UASYNC* ua, socket_t sock, socket_t_callback_t |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
return &ua->sockets->sockets[index]; |
|
|
|
return (void*)(intptr_t)fd; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Remove socket by socket_t
|
|
|
|
// Remove socket by socket_t
|
|
|
|
@ -836,51 +832,68 @@ static void rebuild_poll_fds(struct UASYNC* ua) { |
|
|
|
ua->poll_fds_dirty = 0; |
|
|
|
ua->poll_fds_dirty = 0; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Process events from epoll (Linux only)
|
|
|
|
// Process events from epoll (Linux only). Each callback group re-looks up node
|
|
|
|
|
|
|
|
// via socket_array_get to survive realloc triggered by other callbacks.
|
|
|
|
#if HAS_EPOLL |
|
|
|
#if HAS_EPOLL |
|
|
|
static void process_epoll_events(struct UASYNC* ua, struct epoll_event* events, int n_events) { |
|
|
|
static void process_epoll_events(struct UASYNC* ua, struct epoll_event* events, int n_events) { |
|
|
|
for (int i = 0; i < n_events; i++) { |
|
|
|
for (int i = 0; i < n_events; i++) { |
|
|
|
// Check if this is the wakeup fd (data.ptr is NULL)
|
|
|
|
if (events[i].data.fd == -1) { |
|
|
|
if (events[i].data.ptr == NULL) { |
|
|
|
|
|
|
|
if (events[i].events & EPOLLIN) { |
|
|
|
if (events[i].events & EPOLLIN) { |
|
|
|
drain_wakeup_pipe(ua); |
|
|
|
drain_wakeup_pipe(ua); |
|
|
|
} |
|
|
|
} |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Socket event
|
|
|
|
int fd = events[i].data.fd; |
|
|
|
struct socket_node* node = (struct socket_node*)events[i].data.ptr; |
|
|
|
|
|
|
|
if (!node || !node->active) continue; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Check for error conditions first */ |
|
|
|
|
|
|
|
if (events[i].events & (EPOLLERR | EPOLLHUP)) { |
|
|
|
if (events[i].events & (EPOLLERR | EPOLLHUP)) { |
|
|
|
if (node->except_cbk) { |
|
|
|
struct socket_node* node = socket_array_get(ua->sockets, fd); |
|
|
|
node->except_cbk(node->fd, node->user_data); |
|
|
|
if (node && node->active && node->except_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = node->except_cbk; |
|
|
|
|
|
|
|
int node_fd = node->fd; |
|
|
|
|
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(node_fd, ud); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Read readiness - use appropriate callback based on socket type */ |
|
|
|
|
|
|
|
if (events[i].events & EPOLLIN) { |
|
|
|
if (events[i].events & EPOLLIN) { |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
struct socket_node* node = socket_array_get(ua->sockets, fd); |
|
|
|
if (node->read_cbk_sock) { |
|
|
|
if (node && node->active) { |
|
|
|
node->read_cbk_sock(node->sock, node->user_data); |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
} |
|
|
|
if (node->read_cbk_sock) { |
|
|
|
} else { |
|
|
|
socket_t_callback_t cb = node->read_cbk_sock; |
|
|
|
if (node->read_cbk) { |
|
|
|
socket_t sock = node->sock; |
|
|
|
node->read_cbk(node->fd, node->user_data); |
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(sock, ud); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (node->read_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = node->read_cbk; |
|
|
|
|
|
|
|
int node_fd = node->fd; |
|
|
|
|
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(node_fd, ud); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Write readiness - use appropriate callback based on socket type */ |
|
|
|
|
|
|
|
if (events[i].events & EPOLLOUT) { |
|
|
|
if (events[i].events & EPOLLOUT) { |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
struct socket_node* node = socket_array_get(ua->sockets, fd); |
|
|
|
if (node->write_cbk_sock) { |
|
|
|
if (node && node->active) { |
|
|
|
node->write_cbk_sock(node->sock, node->user_data); |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
} |
|
|
|
if (node->write_cbk_sock) { |
|
|
|
} else { |
|
|
|
socket_t_callback_t cb = node->write_cbk_sock; |
|
|
|
if (node->write_cbk) { |
|
|
|
socket_t sock = node->sock; |
|
|
|
node->write_cbk(node->fd, node->user_data); |
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(sock, ud); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (node->write_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = node->write_cbk; |
|
|
|
|
|
|
|
int node_fd = node->fd; |
|
|
|
|
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(node_fd, ud); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1046,10 +1059,14 @@ void uasync_poll(struct UASYNC* ua, int timeout_tb) { |
|
|
|
if (!node->active) continue; |
|
|
|
if (!node->active) continue; |
|
|
|
|
|
|
|
|
|
|
|
SOCKET s; |
|
|
|
SOCKET s; |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
int fd; |
|
|
|
|
|
|
|
int type = node->type; |
|
|
|
|
|
|
|
if (type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
s = node->sock; |
|
|
|
s = node->sock; |
|
|
|
|
|
|
|
fd = (int)(intptr_t)s; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
s = (SOCKET)node->fd; |
|
|
|
s = (SOCKET)node->fd; |
|
|
|
|
|
|
|
fd = node->fd; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
int has_read = FD_ISSET(s, &read_fds); |
|
|
|
int has_read = FD_ISSET(s, &read_fds); |
|
|
|
@ -1059,31 +1076,59 @@ void uasync_poll(struct UASYNC* ua, int timeout_tb) { |
|
|
|
if (!has_read && !has_write && !has_except) continue; |
|
|
|
if (!has_read && !has_write && !has_except) continue; |
|
|
|
|
|
|
|
|
|
|
|
if (has_except) { |
|
|
|
if (has_except) { |
|
|
|
if (node->except_cbk) { |
|
|
|
struct socket_node* n = (type == SOCKET_NODE_TYPE_SOCK) ? |
|
|
|
node->except_cbk(node->fd, node->user_data); |
|
|
|
socket_array_get_by_sock(ua->sockets, s) : |
|
|
|
|
|
|
|
socket_array_get(ua->sockets, fd); |
|
|
|
|
|
|
|
if (n && n->active && n->except_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = n->except_cbk; |
|
|
|
|
|
|
|
int n_fd = n->fd; |
|
|
|
|
|
|
|
void* ud = n->user_data; |
|
|
|
|
|
|
|
cb(n_fd, ud); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (has_read) { |
|
|
|
if (has_read) { |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
struct socket_node* n = (type == SOCKET_NODE_TYPE_SOCK) ? |
|
|
|
if (node->read_cbk_sock) { |
|
|
|
socket_array_get_by_sock(ua->sockets, s) : |
|
|
|
node->read_cbk_sock(node->sock, node->user_data); |
|
|
|
socket_array_get(ua->sockets, fd); |
|
|
|
} |
|
|
|
if (n && n->active) { |
|
|
|
} else { |
|
|
|
if (type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
if (node->read_cbk) { |
|
|
|
if (n->read_cbk_sock) { |
|
|
|
node->read_cbk(node->fd, node->user_data); |
|
|
|
socket_t_callback_t cb = n->read_cbk_sock; |
|
|
|
|
|
|
|
socket_t sock = n->sock; |
|
|
|
|
|
|
|
void* ud = n->user_data; |
|
|
|
|
|
|
|
cb(sock, ud); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (n->read_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = n->read_cbk; |
|
|
|
|
|
|
|
int n_fd = n->fd; |
|
|
|
|
|
|
|
void* ud = n->user_data; |
|
|
|
|
|
|
|
cb(n_fd, ud); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if (has_write) { |
|
|
|
if (has_write) { |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
struct socket_node* n = (type == SOCKET_NODE_TYPE_SOCK) ? |
|
|
|
if (node->write_cbk_sock) { |
|
|
|
socket_array_get_by_sock(ua->sockets, s) : |
|
|
|
node->write_cbk_sock(node->sock, node->user_data); |
|
|
|
socket_array_get(ua->sockets, fd); |
|
|
|
} |
|
|
|
if (n && n->active) { |
|
|
|
} else { |
|
|
|
if (type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
if (node->write_cbk) { |
|
|
|
if (n->write_cbk_sock) { |
|
|
|
node->write_cbk(node->fd, node->user_data); |
|
|
|
socket_t_callback_t cb = n->write_cbk_sock; |
|
|
|
|
|
|
|
socket_t sock = n->sock; |
|
|
|
|
|
|
|
void* ud = n->user_data; |
|
|
|
|
|
|
|
cb(sock, ud); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (n->write_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = n->write_cbk; |
|
|
|
|
|
|
|
int n_fd = n->fd; |
|
|
|
|
|
|
|
void* ud = n->user_data; |
|
|
|
|
|
|
|
cb(n_fd, ud); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1124,51 +1169,74 @@ void uasync_poll(struct UASYNC* ua, int timeout_tb) { |
|
|
|
continue; |
|
|
|
continue; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Socket event - lookup by fd */ |
|
|
|
int fd = ua->poll_fds[i].fd; |
|
|
|
struct socket_node* node = socket_array_get(ua->sockets, ua->poll_fds[i].fd); |
|
|
|
|
|
|
|
if (!node) { // Try by socket_t (in case this is a socket)
|
|
|
|
|
|
|
|
socket_t lookup_sock = ua->poll_fds[i].fd; |
|
|
|
|
|
|
|
node = socket_array_get_by_sock(ua->sockets, lookup_sock); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (!node) continue; // Socket may have been removed
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Check for error conditions first */ |
|
|
|
/* Check for error conditions first — fresh lookup per group */ |
|
|
|
if (ua->poll_fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) { |
|
|
|
if (ua->poll_fds[i].revents & (POLLERR | POLLHUP | POLLNVAL)) { |
|
|
|
/* Treat as exceptional condition */ |
|
|
|
struct socket_node* node = socket_array_get(ua->sockets, fd); |
|
|
|
if (node->except_cbk) { |
|
|
|
if (!node) node = socket_array_get_by_sock(ua->sockets, (socket_t)fd); |
|
|
|
node->except_cbk(node->fd, node->user_data); |
|
|
|
if (node && node->active && node->except_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = node->except_cbk; |
|
|
|
|
|
|
|
int n_fd = node->fd; |
|
|
|
|
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(n_fd, ud); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Exceptional data (out-of-band) */ |
|
|
|
/* Exceptional data (out-of-band) */ |
|
|
|
if (ua->poll_fds[i].revents & POLLPRI) { |
|
|
|
if (ua->poll_fds[i].revents & POLLPRI) { |
|
|
|
if (node->except_cbk) { |
|
|
|
struct socket_node* node = socket_array_get(ua->sockets, fd); |
|
|
|
node->except_cbk(node->fd, node->user_data); |
|
|
|
if (!node) node = socket_array_get_by_sock(ua->sockets, (socket_t)fd); |
|
|
|
|
|
|
|
if (node && node->active && node->except_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = node->except_cbk; |
|
|
|
|
|
|
|
int n_fd = node->fd; |
|
|
|
|
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(n_fd, ud); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Read readiness - use appropriate callback based on socket type */ |
|
|
|
/* Read readiness — fresh lookup, copy cb+args before call */ |
|
|
|
if (ua->poll_fds[i].revents & POLLIN) { |
|
|
|
if (ua->poll_fds[i].revents & POLLIN) { |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
struct socket_node* node = socket_array_get(ua->sockets, fd); |
|
|
|
if (node->read_cbk_sock) { |
|
|
|
if (!node) node = socket_array_get_by_sock(ua->sockets, (socket_t)fd); |
|
|
|
node->read_cbk_sock(node->sock, node->user_data); |
|
|
|
if (node && node->active) { |
|
|
|
} |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
} else { |
|
|
|
if (node->read_cbk_sock) { |
|
|
|
if (node->read_cbk) { |
|
|
|
socket_t_callback_t cb = node->read_cbk_sock; |
|
|
|
node->read_cbk(node->fd, node->user_data); |
|
|
|
socket_t sock = node->sock; |
|
|
|
|
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(sock, ud); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (node->read_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = node->read_cbk; |
|
|
|
|
|
|
|
int n_fd = node->fd; |
|
|
|
|
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(n_fd, ud); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/* Write readiness - use appropriate callback based on socket type */ |
|
|
|
/* Write readiness — fresh lookup, copy cb+args before call */ |
|
|
|
if (ua->poll_fds[i].revents & POLLOUT) { |
|
|
|
if (ua->poll_fds[i].revents & POLLOUT) { |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
struct socket_node* node = socket_array_get(ua->sockets, fd); |
|
|
|
if (node->write_cbk_sock) { |
|
|
|
if (!node) node = socket_array_get_by_sock(ua->sockets, (socket_t)fd); |
|
|
|
node->write_cbk_sock(node->sock, node->user_data); |
|
|
|
if (node && node->active) { |
|
|
|
} |
|
|
|
if (node->type == SOCKET_NODE_TYPE_SOCK) { |
|
|
|
} else { |
|
|
|
if (node->write_cbk_sock) { |
|
|
|
if (node->write_cbk) { |
|
|
|
socket_t_callback_t cb = node->write_cbk_sock; |
|
|
|
node->write_cbk(node->fd, node->user_data); |
|
|
|
socket_t sock = node->sock; |
|
|
|
|
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(sock, ud); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
if (node->write_cbk) { |
|
|
|
|
|
|
|
socket_callback_t cb = node->write_cbk; |
|
|
|
|
|
|
|
int n_fd = node->fd; |
|
|
|
|
|
|
|
void* ud = node->user_data; |
|
|
|
|
|
|
|
cb(n_fd, ud); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -1294,7 +1362,7 @@ struct UASYNC* uasync_create(void) { |
|
|
|
if (ua->wakeup_initialized) { |
|
|
|
if (ua->wakeup_initialized) { |
|
|
|
struct epoll_event ev; |
|
|
|
struct epoll_event ev; |
|
|
|
ev.events = EPOLLIN; |
|
|
|
ev.events = EPOLLIN; |
|
|
|
ev.data.ptr = NULL; // NULL ptr indicates wakeup fd
|
|
|
|
ev.data.fd = -1; |
|
|
|
if (epoll_ctl(ua->epoll_fd, EPOLL_CTL_ADD, ua->wakeup_pipe[0], &ev) < 0) { |
|
|
|
if (epoll_ctl(ua->epoll_fd, EPOLL_CTL_ADD, ua->wakeup_pipe[0], &ev) < 0) { |
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_UASYNC, "Failed to add wakeup pipe to epoll: %s", strerror(errno)); |
|
|
|
DEBUG_WARN(DEBUG_CATEGORY_UASYNC, "Failed to add wakeup pipe to epoll: %s", strerror(errno)); |
|
|
|
} |
|
|
|
} |
|
|
|
|