piscisaureus / wepoll

wepoll: fast epoll for windows⁧ 🎭

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

win x64 sdk:10.0.18362.0 + VS2019, Udp-svr EPOLLIN WSARecvFrom and Tcp-client EPOLLIN WSARecv() both return(-1) and errno(112), not work?

QingruiHuang opened this issue · comments

commented

// test-multi-poll.c
#include <process.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "test-util.h"
#include "util.h"
#include "wepoll.h"
#include "win.h"

#define PORT_COUNT 10
#define THREADS_PER_PORT 2

#define LISTEN_PORT 12345

typedef struct test_context {
SOCKET sock;
HANDLE port;
uint64_t data;
HANDLE thread;
} test_context_t;

static SOCKET create_socket(unsigned short port) {
SOCKET sock;
struct sockaddr_in address;
unsigned long one = 1;
int r;

sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
check(sock > 0);

address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
r = bind(sock, (struct sockaddr*) &address, sizeof address);
check(r == 0);

r = ioctlsocket(sock, (long) FIONBIO, &one);
check(r == 0);

return sock;
}

static void send_message(SOCKET sock, unsigned short port) {
char hello[] = "hello";
struct sockaddr_in address;
WSABUF buf;
DWORD bytes_sent;
int r;

address.sin_family = AF_INET;
address.sin_port = htons(port);
address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);

buf.buf = hello;
buf.len = sizeof(hello);

r = WSASendTo(sock,
&buf,
1,
&bytes_sent,
0,
(struct sockaddr*) &address,
sizeof address,
NULL,
NULL);
check(r >= 0);
}

static unsigned int __stdcall poll_thread(void* arg) {
test_context_t* context = arg;
struct epoll_event ev_out;
struct sockaddr_in adr_ss;
int adr_len = sizeof(struct sockaddr_in);
WSABUF rcvbuf = {0};
DWORD count = 0;
int r;

memset(&ev_out, 0, sizeof ev_out);
r = epoll_wait(context->port, &ev_out, 1, -1);
check(r == 1);

check(ev_out.events == EPOLLIN);
check(ev_out.data.u64 == context->data);

printf("Got event (port %p, thread %p)\n", context->port, context->thread);

rcvbuf.len = 100;
rcvbuf.buf = malloc(sizeof(CHAR) * rcvbuf.len);
memset(rcvbuf.buf, 0x00, sizeof(CHAR) * rcvbuf.len);

r = WSARecvFrom(context->sock, &rcvbuf, 1, &count, NULL, (struct sockaddr*)&adr_ss, &adr_len, NULL, NULL);

printf("WSARecvFrom (port %p, thread %p) -> [r:%d,c:%lu]={%s}\n", context->port, context->thread, r, count, rcvbuf.buf);

free(rcvbuf.buf);

return 0;
}

int main(void) {
HANDLE ports[PORT_COUNT];
test_context_t contexts[PORT_COUNT][THREADS_PER_PORT];
WSADATA wsa_data;
size_t i, j;
int r;

/* Initialize winsock. */
r = WSAStartup(MAKEWORD(2, 2), &wsa_data);
check(r == 0);

SOCKET send_sock = create_socket(0);
SOCKET recv_sock = create_socket(LISTEN_PORT);

/* Create PORT_COUNT epoll ports which, will be polled by THREADS_PER_PORT

  • threads. */
    for (i = 0; i < array_count(contexts); i++) {
    HANDLE port;
    struct epoll_event ev;
/* Create epoll port. */
port = epoll_create1(0);
check(port != NULL);
ports[i] = port;

/* Register recv_sock with the epoll port. */
ev.events = EPOLLIN;
ev.data.u64 = (uint64_t) rand();
r = epoll_ctl(port, EPOLL_CTL_ADD, recv_sock, &ev);
check(r == 0);

/* Start THREADS_PER_PORT threads which will all poll the port. */
for (j = 0; j < array_count(contexts[i]); j++) {
  test_context_t* context = &contexts[i][j];
  HANDLE thread;

  /* Prepare context information for the polling thread. */
  context->port = port;
  context->sock = recv_sock;
  context->data = ev.data.u64;

  /* Start thread. */
  thread = (HANDLE) _beginthreadex(
      NULL, 0, poll_thread, (void*) context, 0, NULL);
  check(thread != INVALID_HANDLE_VALUE);
  context->thread = thread;
}

}

/* Sleep for a while to give all threads a chance to finish initializing. */
Sleep(500);

/* Send a message to the receiving socket. */
send_message(send_sock, LISTEN_PORT);

/* Wait for all threads to exit and clean up after them. */
for (i = 0; i < array_count(contexts); i++) {
for (j = 0; j < array_count(contexts[i]); j++) {
HANDLE thread = contexts[i][j].thread;
DWORD wr = WaitForSingleObject(thread, INFINITE);
check(wr == WAIT_OBJECT_0);
CloseHandle(thread);
}
}

/* Close all epoll ports. */
for (i = 0; i < array_count(ports); i++) {
HANDLE port = ports[i];
r = epoll_close(port);
check(r == 0);
}

return 0;
}

// out
E:\GitHub\wepoll\cmake-build-debug\test-multi-poll.exe
Got event (port 0000000000000108, thread 0000000000000114)
Got event (port 0000000000000128, thread 0000000000000130)
WSARecvFrom (port 0000000000000128, thread 0000000000000130) -> [r:-1,c:0]={}
Got event (port 0000000000000148, thread 0000000000000158)
WSARecvFrom (port 0000000000000148, thread 0000000000000158) -> [r:-1,c:0]={}
Got event (port 00000000000000E8, thread 00000000000000F0)
WSARecvFrom (port 00000000000000E8, thread 00000000000000F0) -> [r:-1,c:0]={}
Got event (port 0000000000000160, thread 0000000000000170)
WSARecvFrom (port 0000000000000160, thread 0000000000000170) -> [r:-1,c:0]={}
Got event (port 00000000000000E8, thread 00000000000000F4)
Got event (port 0000000000000160, thread 000000000000016C)
WSARecvFrom (port 0000000000000160, thread 000000000000016C) -> [r:-1,c:0]={}
Got event (port 00000000000000F8, thread 0000000000000100)
WSARecvFrom (port 00000000000000F8, thread 0000000000000100) -> [r:-1,c:0]={}
Got event (port 0000000000000128, thread 0000000000000134)
WSARecvFrom (port 0000000000000128, thread 0000000000000134) -> [r:-1,c:0]={}
Got event (port 0000000000000108, thread 0000000000000110)
WSARecvFrom (port 0000000000000108, thread 0000000000000110) -> [r:-1,c:0]={}
Got event (port 0000000000000138, thread 0000000000000140)
WSARecvFrom (port 0000000000000138, thread 0000000000000140) -> [r:-1,c:0]={}
WSARecvFrom (port 0000000000000108, thread 0000000000000114) -> [r:-1,c:0]={}
Got event (port 0000000000000118, thread 0000000000000124)
Got event (port 0000000000000138, thread 0000000000000144)
Got event (port 0000000000000118, thread 0000000000000120)
Got event (port 0000000000000148, thread 0000000000000154)
WSARecvFrom (port 00000000000000E8, thread 00000000000000F4) -> [r:-1,c:0]={}
Got event (port 00000000000000F8, thread 0000000000000104)
WSARecvFrom (port 00000000000000F8, thread 0000000000000104) -> [r:-1,c:0]={}
Got event (port 00000000000000C8, thread 00000000000000D4)
Got event (port 00000000000000C8, thread 00000000000000D0)
WSARecvFrom (port 00000000000000C8, thread 00000000000000D0) -> [r:-1,c:0]={}
WSARecvFrom (port 0000000000000118, thread 0000000000000124) -> [r:-1,c:0]={}
WSARecvFrom (port 0000000000000138, thread 0000000000000144) -> [r:-1,c:0]={}
WSARecvFrom (port 0000000000000118, thread 0000000000000120) -> [r:-1,c:0]={}
WSARecvFrom (port 0000000000000148, thread 0000000000000154) -> [r:-1,c:0]={}
Got event (port 00000000000000D8, thread 00000000000000E4)
WSARecvFrom (port 00000000000000C8, thread 00000000000000D4) -> [r:-1,c:0]={}
Got event (port 00000000000000D8, thread 00000000000000E0)
WSARecvFrom (port 00000000000000D8, thread 00000000000000E4) -> [r:-1,c:0]={}
WSARecvFrom (port 00000000000000D8, thread 00000000000000E0) -> [r:-1,c:0]={}

Process finished with exit code 0

What is the issue?

commented

i add some code in master/test-multi-poll.c -> poll_thread();
when the svr-sock has event [EPOLLIN]
then WSARecvFrom(svr-sock), but return -1, recv nothing, why?

then WSARecvFrom(svr-sock), but return -1, recv nothing, why?

What is the error you get after WSARecvFrom returns -1?

commented

win x64 sdk: Windows Kits\10\Include\10.0.18362.0

errno = 0 or 112 [EINPROGRESS]

Got event (port 000000000000010C, thread 0000000000000114)
WSARecvFrom (port:000000000000010C, thread:0000000000000114, errno:112) -> [r:-1,c:0]={}
Got event (port 00000000000000D4, thread 00000000000000E0)
WSARecvFrom (port:00000000000000D4, thread:00000000000000E0, errno:0) -> [r:-1,c:0]={}

commented

I used wepoll to write a TCP server, tcp-svr EPOLLIN, then accept okey;
but when tcp-client EPOLLIN, WSARecv(clientfd), it also return - 1; I thought I did something wrong, and now I to use your demo for testing, and got the same return(-1) and errno(112).
EPOLLOUT hasn't been tested yet。

errno = 0 or 112 [EINPROGRESS]

I'm sorry, please read the (win32) manual first.
Hint: errno is not set after WSARecv/WSARecvFrom failure.