|
|
|
|
@ -373,6 +373,7 @@ static void handle_wakeup(struct UASYNC* ua) {
|
|
|
|
|
while (read(ua->wakeup_pipe[0], buf, sizeof(buf)) > 0) {} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// DEBUG_DEBUG(DEBUG_CATEGORY_TIMERS, "POST: wakeup process");
|
|
|
|
|
// Execute all posted callbacks (in main thread)
|
|
|
|
|
process_posted_tasks(ua); |
|
|
|
|
} |
|
|
|
|
@ -1105,62 +1106,6 @@ struct UASYNC* uasync_create(void) {
|
|
|
|
|
ua->wakeup_initialized = 0; |
|
|
|
|
ua->posted_tasks_head = NULL; |
|
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
// Windows: self-connected UDP socket for wakeup
|
|
|
|
|
SOCKET r = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
|
|
|
|
SOCKET w = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
|
|
|
|
if (r == INVALID_SOCKET || w == INVALID_SOCKET) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_UASYNC, "Failed to create wakeup sockets"); |
|
|
|
|
free(ua); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct sockaddr_in addr = {0}; |
|
|
|
|
addr.sin_family = AF_INET; |
|
|
|
|
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|
|
|
|
addr.sin_port = 0; |
|
|
|
|
|
|
|
|
|
if (bind(r, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR || |
|
|
|
|
getsockname(r, (struct sockaddr*)&addr, &(int){sizeof(addr)}) == SOCKET_ERROR || |
|
|
|
|
connect(w, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) { |
|
|
|
|
closesocket(r); |
|
|
|
|
closesocket(w); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_UASYNC, "Wakeup socket setup failed: %d", WSAGetLastError()); |
|
|
|
|
free(ua); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ua->wakeup_pipe[0] = (int)(intptr_t)r; |
|
|
|
|
ua->wakeup_pipe[1] = (int)(intptr_t)w; |
|
|
|
|
ua->wakeup_initialized = 1; |
|
|
|
|
|
|
|
|
|
u_long mode = 1; |
|
|
|
|
ioctlsocket(r, FIONBIO, &mode); |
|
|
|
|
|
|
|
|
|
// Register the read socket with uasync
|
|
|
|
|
uasync_add_socket_t(ua, r, wakeup_read_callback_win, NULL, NULL, ua); // ← ua как user_data
|
|
|
|
|
// uasync_add_socket_t(ua, r, wakeup_read_callback_win, NULL, NULL, NULL);
|
|
|
|
|
InitializeCriticalSection(&ua->posted_lock); |
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
// POSIX pipe
|
|
|
|
|
if (pipe(ua->wakeup_pipe) != 0) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_UASYNC, "pipe() failed: %s", strerror(errno)); |
|
|
|
|
free(ua); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
ua->wakeup_initialized = 1; |
|
|
|
|
|
|
|
|
|
fcntl(ua->wakeup_pipe[0], F_SETFL, fcntl(ua->wakeup_pipe[0], F_GETFL, 0) | O_NONBLOCK); |
|
|
|
|
fcntl(ua->wakeup_pipe[1], F_SETFL, fcntl(ua->wakeup_pipe[1], F_GETFL, 0) | O_NONBLOCK); |
|
|
|
|
|
|
|
|
|
if (!ua->use_epoll) { |
|
|
|
|
uasync_add_socket(ua, ua->wakeup_pipe[0], wakeup_read_callback_posix, NULL, NULL, ua); // ← ua
|
|
|
|
|
} |
|
|
|
|
pthread_mutex_init(&ua->posted_lock, NULL); |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
ua->sockets = socket_array_create(16); |
|
|
|
|
if (!ua->sockets) { |
|
|
|
|
if (ua->wakeup_initialized) { |
|
|
|
|
@ -1217,6 +1162,62 @@ struct UASYNC* uasync_create(void) {
|
|
|
|
|
} |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef _WIN32 |
|
|
|
|
// Windows: self-connected UDP socket for wakeup
|
|
|
|
|
SOCKET r = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
|
|
|
|
SOCKET w = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
|
|
|
|
if (r == INVALID_SOCKET || w == INVALID_SOCKET) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_UASYNC, "Failed to create wakeup sockets"); |
|
|
|
|
free(ua); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
struct sockaddr_in addr = {0}; |
|
|
|
|
addr.sin_family = AF_INET; |
|
|
|
|
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); |
|
|
|
|
addr.sin_port = 0; |
|
|
|
|
|
|
|
|
|
if (bind(r, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR || |
|
|
|
|
getsockname(r, (struct sockaddr*)&addr, &(int){sizeof(addr)}) == SOCKET_ERROR || |
|
|
|
|
connect(w, (struct sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) { |
|
|
|
|
closesocket(r); |
|
|
|
|
closesocket(w); |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_UASYNC, "Wakeup socket setup failed: %d", WSAGetLastError()); |
|
|
|
|
free(ua); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ua->wakeup_pipe[0] = (int)(intptr_t)r; |
|
|
|
|
ua->wakeup_pipe[1] = (int)(intptr_t)w; |
|
|
|
|
ua->wakeup_initialized = 1; |
|
|
|
|
|
|
|
|
|
u_long mode = 1; |
|
|
|
|
ioctlsocket(r, FIONBIO, &mode); |
|
|
|
|
|
|
|
|
|
// Register the read socket with uasync
|
|
|
|
|
uasync_add_socket_t(ua, r, wakeup_read_callback_win, NULL, NULL, ua); // ← ua как user_data
|
|
|
|
|
// uasync_add_socket_t(ua, r, wakeup_read_callback_win, NULL, NULL, NULL);
|
|
|
|
|
InitializeCriticalSection(&ua->posted_lock); |
|
|
|
|
|
|
|
|
|
#else |
|
|
|
|
// POSIX pipe
|
|
|
|
|
if (pipe(ua->wakeup_pipe) != 0) { |
|
|
|
|
DEBUG_ERROR(DEBUG_CATEGORY_UASYNC, "pipe() failed: %s", strerror(errno)); |
|
|
|
|
free(ua); |
|
|
|
|
return NULL; |
|
|
|
|
} |
|
|
|
|
ua->wakeup_initialized = 1; |
|
|
|
|
|
|
|
|
|
fcntl(ua->wakeup_pipe[0], F_SETFL, fcntl(ua->wakeup_pipe[0], F_GETFL, 0) | O_NONBLOCK); |
|
|
|
|
fcntl(ua->wakeup_pipe[1], F_SETFL, fcntl(ua->wakeup_pipe[1], F_GETFL, 0) | O_NONBLOCK); |
|
|
|
|
|
|
|
|
|
if (!ua->use_epoll) { |
|
|
|
|
uasync_add_socket(ua, ua->wakeup_pipe[0], wakeup_read_callback_posix, NULL, NULL, ua); // ← ua
|
|
|
|
|
} |
|
|
|
|
pthread_mutex_init(&ua->posted_lock, NULL); |
|
|
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
return ua; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@ -1436,6 +1437,7 @@ void uasync_post(struct UASYNC* ua, uasync_post_callback_t callback, void* arg)
|
|
|
|
|
pthread_mutex_unlock(&ua->posted_lock); |
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
// DEBUG_DEBUG(DEBUG_CATEGORY_TIMERS, "POST: wakeup send");
|
|
|
|
|
uasync_wakeup(ua); // будим mainloop
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|