Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions event/epoll.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ typedef struct epoll_ctx_s {
int iowatcher_init(hloop_t* loop) {
if (loop->iowatcher) return 0;
epoll_handle_t epfd = epoll_create(EVENTS_INIT_SIZE);
#ifdef OS_WIN
if (epfd == NULL) {
#else
if (epfd < 0) {
#endif
hloge("epoll_create failed: %d", socket_errno());
return -1;
}
Expand Down
9 changes: 9 additions & 0 deletions unittest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,14 @@ set(HTTP_JS_UNITTEST_TARGETS ${HTTP_JS_UNITTEST_TARGETS} http_js_mqtt_test)
endif()
endif()

# ------event: Windows epoll initialization------
if(WIN32 AND WITH_WEPOLL)
add_executable(epoll_init_test epoll_init_test.c ../event/wepoll/wepoll.c)
target_include_directories(epoll_init_test PRIVATE .. ../base ../ssl ../event)
target_link_libraries(epoll_init_test ${HV_LIBRARIES})
set(EVENT_UNITTEST_TARGETS epoll_init_test)
endif()

# ------event: async dns------
add_executable(hdns_test hdns_test.c)
target_include_directories(hdns_test PRIVATE .. ../base ../ssl ../event)
Expand Down Expand Up @@ -231,6 +239,7 @@ add_custom_target(unittest DEPENDS
${HTTP_UNITTEST_TARGETS}
${HTTP_LUA_UNITTEST_TARGETS}
${HTTP_JS_UNITTEST_TARGETS}
${EVENT_UNITTEST_TARGETS}
hdns_test
hdns_benchmark
${REDIS_UNITTEST_TARGETS}
Expand Down
70 changes: 70 additions & 0 deletions unittest/epoll_init_test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* Exercise failed Windows backend initialization and retry. Only the first
* creation fails artificially; successful ports and cleanup use real wepoll. */
#include "hevent.h"
#include "wepoll/wepoll.h"

static unsigned int create_calls;
static int fail_next_create;

static HANDLE test_epoll_create(int size) {
++create_calls;
if (fail_next_create) {
fail_next_create = 0;
errno = ENOMEM;
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
return NULL;
}
return epoll_create(size);
}

/* Keep the backend under test separate from the linked library's watcher. */
#define epoll_create test_epoll_create
#define iowatcher_init test_iowatcher_init
#define iowatcher_cleanup test_iowatcher_cleanup
#define iowatcher_add_event test_iowatcher_add_event
#define iowatcher_del_event test_iowatcher_del_event
#define iowatcher_poll_events test_iowatcher_poll_events
#include "../event/epoll.c"
#undef epoll_create
#undef iowatcher_init
#undef iowatcher_cleanup
#undef iowatcher_add_event
#undef iowatcher_del_event
#undef iowatcher_poll_events

/* Assertions must remain active in optimized builds. */
static void require(int condition, const char *message) {
if (!condition) {
fprintf(stderr, "epoll_init_test: %s (errno=%d, winerror=%lu)\n", message, errno, (unsigned long)GetLastError());
exit(EXIT_FAILURE);
}
}

int main(void) {
hloop_t loop;
HANDLE port;
DWORD flags;
memset(&loop, 0, sizeof(loop));

fail_next_create = 1;
require(test_iowatcher_init(&loop) == -1, "failed epoll_create was reported as successful initialization");
require(loop.iowatcher == NULL, "failed initialization published an invalid context");
require(create_calls == 1, "creation failure did not reach the backend");

require(test_iowatcher_init(&loop) == 0, "initialization did not recover after creation failure");
require(create_calls == 2 && loop.iowatcher != NULL, "retry did not create a new port");
port = ((epoll_ctx_t *)loop.iowatcher)->epfd;
require(port != NULL && GetHandleInformation(port, &flags), "retry did not create a valid native port");
require(test_iowatcher_init(&loop) == 0 && create_calls == 2, "initialization was not idempotent");
require(test_iowatcher_cleanup(&loop) == 0 && loop.iowatcher == NULL, "cleanup retained the port context");
require(!GetHandleInformation(port, &flags) && GetLastError() == ERROR_INVALID_HANDLE, "cleanup did not close the native port");
require(test_iowatcher_cleanup(&loop) == 0, "repeated cleanup failed");

require(test_iowatcher_init(&loop) == 0 && create_calls == 3, "ordinary creation after cleanup failed");
port = ((epoll_ctx_t *)loop.iowatcher)->epfd;
require(port != NULL && GetHandleInformation(port, &flags), "ordinary creation did not produce a valid native port");
require(test_iowatcher_cleanup(&loop) == 0 && loop.iowatcher == NULL, "ordinary port cleanup failed");
require(!GetHandleInformation(port, &flags) && GetLastError() == ERROR_INVALID_HANDLE, "ordinary cleanup did not close the native port");
puts("epoll_init_test passed");
return 0;
}
Loading