Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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? #24

Closed
QingruiHuang opened this issue Jun 15, 2021 · 6 comments

Comments

@QingruiHuang
Copy link

// 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

@piscisaureus
Copy link
Owner

What is the issue?

@QingruiHuang
Copy link
Author

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?

@piscisaureus
Copy link
Owner

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

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

@QingruiHuang
Copy link
Author

QingruiHuang commented Jun 17, 2021

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]={}

@QingruiHuang
Copy link
Author

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。

@QingruiHuang QingruiHuang changed the title win10_x64 + VS2019, WSARecvFrom not work? 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? Jun 17, 2021
@piscisaureus
Copy link
Owner

errno = 0 or 112 [EINPROGRESS]

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants