Fix u_async: Windows socket registration, timers, and poll issues
- Remove FD_SETSIZE check for Windows sockets (can have any value) - Fix process_timeouts to handle all expired timers (continue instead of break) - Handle case when no sockets to poll (sleep instead of calling poll) - Disable wakeup pipe on Windows (incompatible with WSAPoll) - Add gettimeofday and ssize_t implementations for Windows
This commit is contained in:
1 parent
53c7330a7f
commit
c8af35c4b9
2 files changed
+58
-7
No files matched your search
+28
-2
@@ -39,8 +39,34 @@
|
||||
#define POLLPRI 0x0002
|
||||
#endif
|
||||
|
||||
// gettimeofday for Windows (use system implementation if available)
|
||||
#include <sys/time.h>
|
||||
// ssize_t for Windows (signed size type)
|
||||
#ifndef _SSIZE_T_DEFINED
|
||||
typedef long ssize_t;
|
||||
#define _SSIZE_T_DEFINED
|
||||
#endif
|
||||
|
||||
// gettimeofday for Windows - provide our own implementation
|
||||
static inline int gettimeofday(struct timeval *tv, void *tz) {
|
||||
FILETIME ft;
|
||||
unsigned __int64 tmpres = 0;
|
||||
|
||||
if (tv != NULL) {
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
tmpres |= ft.dwHighDateTime;
|
||||
tmpres <<= 32;
|
||||
tmpres |= ft.dwLowDateTime;
|
||||
// Convert from 100-nanosecond intervals to microseconds
|
||||
tmpres /= 10;
|
||||
// Convert to Unix epoch (January 1, 1970)
|
||||
tmpres -= 11644473600000000ULL;
|
||||
tv->tv_sec = (long)(tmpres / 1000000UL);
|
||||
tv->tv_usec = (long)(tmpres % 1000000UL);
|
||||
}
|
||||
|
||||
// tz parameter is ignored (for compatibility with POSIX)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Pipe creation for Windows
|
||||
static inline int platform_pipe(int pipefd[2]) {
|
||||
|
||||
+30
-5
@@ -112,7 +112,11 @@ static int socket_array_add_internal(struct socket_array* sa, int fd, socket_t s
|
||||
socket_callback_t read_cbk_fd, socket_callback_t write_cbk_fd,
|
||||
socket_t_callback_t read_cbk_sock, socket_t_callback_t write_cbk_sock,
|
||||
socket_callback_t except_cbk, void* user_data) {
|
||||
if (!sa || fd < 0 || fd >= FD_SETSIZE) return -1;
|
||||
if (!sa || fd < 0) return -1;
|
||||
// FD_SETSIZE check only for POSIX systems - Windows sockets can have any value
|
||||
#ifndef _WIN32
|
||||
if (fd >= FD_SETSIZE) return -1;
|
||||
#endif
|
||||
if (fd >= sa->capacity) {
|
||||
// Need to resize - double the capacity
|
||||
int new_capacity = sa->capacity * 2;
|
||||
@@ -197,10 +201,11 @@ static int socket_array_add_socket_t(struct socket_array* sa, socket_t sock, soc
|
||||
// On Windows, SOCKET is UINT_PTR, so we need to handle indexing differently
|
||||
#ifdef _WIN32
|
||||
int fd = (int)(intptr_t)sock; // Use socket value as index on Windows (simplified)
|
||||
if (fd < 0) return -1; // Windows sockets can have any value, only check negative
|
||||
#else
|
||||
int fd = sock; // On POSIX, socket_t is int
|
||||
#endif
|
||||
if (fd < 0 || fd >= FD_SETSIZE) return -1;
|
||||
#endif
|
||||
return socket_array_add_internal(sa, fd, sock, SOCKET_NODE_TYPE_SOCK,
|
||||
NULL, NULL, read_cbk, write_cbk, except_cbk, user_data);
|
||||
}
|
||||
@@ -330,7 +335,7 @@ static void process_timeouts(struct UASYNC* ua) {
|
||||
node->ua->timer_free_count++;
|
||||
}
|
||||
free(node);
|
||||
break;
|
||||
continue; // Process next expired timeout
|
||||
}
|
||||
}
|
||||
|
||||
@@ -765,7 +770,20 @@ void uasync_poll(struct UASYNC* ua, int timeout_tb) {
|
||||
// Include wakeup pipe if initialized
|
||||
int wakeup_fd_present = ua->wakeup_initialized && ua->wakeup_pipe[0] >= 0;
|
||||
int total_fds = socket_count + wakeup_fd_present;
|
||||
|
||||
|
||||
// If no sockets to poll, just wait and process timeouts
|
||||
if (total_fds == 0) {
|
||||
if (timeout_ms > 0) {
|
||||
#ifdef _WIN32
|
||||
Sleep(timeout_ms);
|
||||
#else
|
||||
usleep(timeout_ms * 1000);
|
||||
#endif
|
||||
}
|
||||
process_timeouts(ua);
|
||||
return;
|
||||
}
|
||||
|
||||
// Rebuild poll_fds if dirty or not allocated
|
||||
if (ua->poll_fds_dirty || !ua->poll_fds) {
|
||||
rebuild_poll_fds(ua);
|
||||
@@ -881,7 +899,8 @@ struct UASYNC* uasync_create(void) {
|
||||
ua->wakeup_pipe[1] = -1;
|
||||
ua->wakeup_initialized = 0;
|
||||
|
||||
// Create wakeup pipe
|
||||
// Create wakeup pipe (skip on Windows - pipes don't work with poll/WSAPoll)
|
||||
#ifndef _WIN32
|
||||
if (pipe(ua->wakeup_pipe) < 0) {
|
||||
DEBUG_WARN(DEBUG_CATEGORY_UASYNC, "Failed to create wakeup pipe: %s", strerror(errno));
|
||||
// Continue without wakeup mechanism
|
||||
@@ -895,6 +914,12 @@ struct UASYNC* uasync_create(void) {
|
||||
fcntl(ua->wakeup_pipe[0], F_SETFL, flags | O_NONBLOCK);
|
||||
}
|
||||
}
|
||||
#else
|
||||
// On Windows, pipes don't work with WSAPoll - skip wakeup mechanism
|
||||
ua->wakeup_pipe[0] = -1;
|
||||
ua->wakeup_pipe[1] = -1;
|
||||
ua->wakeup_initialized = 0;
|
||||
#endif
|
||||
|
||||
ua->sockets = socket_array_create(16);
|
||||
if (!ua->sockets) {
|
||||
|
||||
Reference in new issue
Block a user