wepoll/test/test-auto-drop-on-close.c
2019-06-12 21:49:11 +02:00

107 lines
2.6 KiB
C

/* This test verifies that sockets are automatically dropped from an epoll set
* when they are closed.
*
* On Linux, a socket would be dropped from the epoll set immediately after the
* call to close(). However on Windows, this isn't possible - wepoll may not
* detect that a socket has been closed until a call to epoll_wait() is made.
*
* There are multiple code paths that detect a closed socket in the wepoll
* implementation; this test attempts to stress all of them.
*/
#include <errno.h>
#include <stdint.h>
#include <stdlib.h>
#include "test-util.h"
#include "util.h"
#include "wepoll.h"
#include "win.h"
static SOCKET create_and_add_socket(HANDLE ephnd, uint32_t events) {
SOCKET sock;
struct epoll_event ev;
int r;
/* Create UDP socket. */
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
check(sock != INVALID_SOCKET);
/* Associate with epoll port. */
ev.events = events;
ev.data.sock = sock;
r = epoll_ctl(ephnd, EPOLL_CTL_ADD, sock, &ev);
check(r == 0);
return sock;
}
static void check_dropped(HANDLE ephnd, SOCKET sock) {
struct epoll_event ev;
int r;
ev.events = EPOLLERR | EPOLLHUP;
ev.data.u64 = 0;
/* Check that EPOLL_CTL_MOD fails. */
r = epoll_ctl(ephnd, EPOLL_CTL_MOD, sock, &ev);
check(r < 0);
check(errno == EBADF);
/* Check that EPOLL_CTL_DEL fails. */
r = epoll_ctl(ephnd, EPOLL_CTL_DEL, sock, &ev);
check(r < 0);
check(errno == EBADF);
}
int main(void) {
HANDLE ephnd;
SOCKET sock1, sock2, sock3, sock4, sock5;
struct epoll_event evs[8];
int r;
ephnd = epoll_create1(0);
check(ephnd != NULL);
sock1 = create_and_add_socket(ephnd, EPOLLIN);
sock2 = create_and_add_socket(ephnd, EPOLLIN);
sock3 = create_and_add_socket(ephnd, EPOLLOUT);
sock4 = create_and_add_socket(ephnd, EPOLLOUT | EPOLLONESHOT);
sock5 = create_and_add_socket(ephnd, 0);
r = closesocket(sock1);
check(r == 0);
r = epoll_wait(ephnd, evs, array_count(evs), -1);
check(r == 2); /* sock3 and sock4 should report events. */
check_dropped(ephnd, sock1);
r = closesocket(sock2);
check(r == 0);
r = closesocket(sock3);
check(r == 0);
r = epoll_wait(ephnd, evs, array_count(evs), 0);
check(r == 0); /* No events should be reported. */
check_dropped(ephnd, sock2);
check_dropped(ephnd, sock3);
r = closesocket(sock4);
check(r == 0);
r = closesocket(sock5);
check(r == 0);
r = epoll_wait(ephnd, evs, array_count(evs), 0);
check(r == 0); /* No events should be reported. */
check_dropped(ephnd, sock4);
check_dropped(ephnd, sock5);
r = epoll_close(ephnd);
check(r == 0);
return 0;
}