version 1.2.0

This commit is contained in:
Bert Belder 2017-12-04 21:09:07 +01:00
commit c053eb280d
2 changed files with 52 additions and 12 deletions

View File

@ -62,7 +62,7 @@ HANDLE epoll_create1(int flags);
* Create a new epoll instance (port).
* `size` is ignored but most be greater than zero.
* `flags` must be zero as there are no supported flags.
* Returns `INVALID_HANDLE_VALUE` on failure.
* Returns `NULL` on failure.
* [man page][man epoll_create]
### epoll_close
@ -88,7 +88,7 @@ int epoll_ctl(HANDLE ephnd,
* `ephnd` must be a HANDLE created by `epoll_create` or `epoll_create1`.
* `op` must be one of `EPOLL_CTL_ADD`, `EPOLL_CTL_MOD`, `EPOLL_CTL_DEL`.
* It is recommended to always explicitly remove a socket from its epoll
set using `EPOLL_CTL_MOD` *before* closing it. As on Linux, sockets
set using `EPOLL_CTL_DEL` *before* closing it. As on Linux, sockets
are automatically removed from the epoll set when they are closed, but
wepoll may not be able to detect this until the next call to
`epoll_wait()`.

View File

@ -364,11 +364,20 @@ static const GUID AFD_PROVIDER_GUID_LIST[] = {
err_set_win_error(error); \
return (value); \
} while (0)
#define return_error(value, ...) _return_error_helper(__VA_ARGS__ + 0, value)
#define _return_handle_error_helper(error, value, handle) \
do { \
err_validate_handle_and_set_win_error((HANDLE) handle, error); \
return (value); \
} while (0)
#define return_handle_error(value, handle, ...) \
_return_handle_error_helper(__VA_ARGS__ + 0, value, handle)
WEPOLL_INTERNAL errno_t err_map_win_error_to_errno(DWORD error);
WEPOLL_INTERNAL void err_set_win_error(DWORD error);
WEPOLL_INTERNAL void err_validate_handle_and_set_win_error(HANDLE handle,
DWORD error);
#define FILE_DEVICE_NETWORK 0x00000012
#define METHOD_BUFFERED 0
@ -1216,8 +1225,9 @@ static HANDLE _epoll_create(void) {
if (reflock_tree_add(&_epoll_handle_tree,
&port_info->handle_tree_node,
(uintptr_t) ephnd) < 0) {
/* This should never happen. */
ep_port_delete(port_info);
return_error(INVALID_HANDLE_VALUE, ERROR_ALREADY_EXISTS);
return_error(NULL, ERROR_ALREADY_EXISTS);
}
return ephnd;
@ -1225,14 +1235,14 @@ static HANDLE _epoll_create(void) {
HANDLE epoll_create(int size) {
if (size <= 0)
return_error(INVALID_HANDLE_VALUE, ERROR_INVALID_PARAMETER);
return_error(NULL, ERROR_INVALID_PARAMETER);
return _epoll_create();
}
HANDLE epoll_create1(int flags) {
if (flags != 0)
return_error(INVALID_HANDLE_VALUE, ERROR_INVALID_PARAMETER);
return_error(NULL, ERROR_INVALID_PARAMETER);
return _epoll_create();
}
@ -1246,7 +1256,7 @@ int epoll_close(HANDLE ephnd) {
tree_node = reflock_tree_del_and_ref(&_epoll_handle_tree, (uintptr_t) ephnd);
if (tree_node == NULL)
return_error(-1, ERROR_INVALID_HANDLE);
return_handle_error(-1, ephnd, ERROR_INVALID_PARAMETER);
port_info = _handle_tree_node_to_port(tree_node);
ep_port_close(port_info);
@ -1267,7 +1277,7 @@ int epoll_ctl(HANDLE ephnd, int op, SOCKET sock, struct epoll_event* ev) {
tree_node =
reflock_tree_find_and_ref(&_epoll_handle_tree, (uintptr_t) ephnd);
if (tree_node == NULL)
return_error(-1, ERROR_INVALID_HANDLE);
return_handle_error(-1, ephnd, ERROR_INVALID_PARAMETER);
port_info = _handle_tree_node_to_port(tree_node);
result = ep_port_ctl(port_info, op, sock, ev);
@ -1291,7 +1301,7 @@ int epoll_wait(HANDLE ephnd,
tree_node =
reflock_tree_find_and_ref(&_epoll_handle_tree, (uintptr_t) ephnd);
if (tree_node == NULL)
return_error(-1, ERROR_INVALID_HANDLE);
return_handle_error(-1, ephnd, ERROR_INVALID_PARAMETER);
port_info = _handle_tree_node_to_port(tree_node);
result = ep_port_wait(port_info, events, maxevents, timeout);
@ -1342,6 +1352,7 @@ int epoll_wait(HANDLE ephnd,
X(ERROR_NETWORK_BUSY, ENETDOWN) \
X(ERROR_NETWORK_UNREACHABLE, ENETUNREACH) \
X(ERROR_NOACCESS, EFAULT) \
X(ERROR_NONPAGED_SYSTEM_RESOURCES, ENOMEM) \
X(ERROR_NOT_ENOUGH_MEMORY, ENOMEM) \
X(ERROR_NOT_ENOUGH_QUOTA, ENOMEM) \
X(ERROR_NOT_FOUND, ENOENT) \
@ -1353,6 +1364,7 @@ int epoll_wait(HANDLE ephnd,
X(ERROR_NO_SYSTEM_RESOURCES, ENOMEM) \
X(ERROR_OPERATION_ABORTED, EINTR) \
X(ERROR_OUT_OF_PAPER, EACCES) \
X(ERROR_PAGED_SYSTEM_RESOURCES, ENOMEM) \
X(ERROR_PAGEFILE_QUOTA, ENOMEM) \
X(ERROR_PATH_NOT_FOUND, ENOENT) \
X(ERROR_PIPE_NOT_CONNECTED, EPIPE) \
@ -1416,6 +1428,26 @@ void err_set_win_error(DWORD error) {
errno = err_map_win_error_to_errno(error);
}
int _check_handle(HANDLE handle) {
DWORD flags;
/* GetHandleInformation() succeeds when passed INVALID_HANDLE_VALUE, so check
* for this condition explicitly. */
if (handle == INVALID_HANDLE_VALUE)
return_error(-1, ERROR_INVALID_HANDLE);
if (!GetHandleInformation(handle, &flags))
return_error(-1);
return 0;
}
void err_validate_handle_and_set_win_error(HANDLE handle, DWORD error) {
if (_check_handle(handle) < 0)
return;
err_set_win_error(error);
}
static bool _initialized = false;
static INIT_ONCE _once = INIT_ONCE_STATIC_INIT;
@ -1624,6 +1656,14 @@ static void _ep_port_free(ep_port_t* port) {
free(port);
}
static HANDLE _ep_port_create_iocp(void) {
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (iocp == NULL)
return_error(NULL);
return iocp;
}
ep_port_t* ep_port_new(HANDLE* iocp_out) {
ep_port_t* port_info;
HANDLE iocp;
@ -1632,8 +1672,8 @@ ep_port_t* ep_port_new(HANDLE* iocp_out) {
if (port_info == NULL)
goto err1;
iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
if (iocp == INVALID_HANDLE_VALUE)
iocp = _ep_port_create_iocp();
if (iocp == NULL)
goto err2;
memset(port_info, 0, sizeof *port_info);
@ -1937,7 +1977,7 @@ ep_sock_t* ep_port_find_socket(ep_port_t* port_info, SOCKET socket) {
ep_sock_t* sock_info = safe_container_of(
tree_find(&port_info->sock_tree, socket), ep_sock_t, tree_node);
if (sock_info == NULL)
return_error(NULL, ERROR_NOT_FOUND);
return_handle_error(NULL, socket, ERROR_NOT_FOUND);
return sock_info;
}