diff options
author | Alan Antonuk <alan.antonuk@gmail.com> | 2015-10-13 20:40:44 -0700 |
---|---|---|
committer | Alan Antonuk <alan.antonuk@gmail.com> | 2015-10-13 23:02:50 -0700 |
commit | ba7c342a55e200d1f72b30d74df1591b0f72de49 (patch) | |
tree | 238fe5ba21cf1b4cb96e0552c9298ee44df3481c | |
parent | e65bb790f7334d347270b7e9a9b455bb1f5f3894 (diff) | |
download | rabbitmq-c-win32_select.tar.gz |
Win32: check exceptfds in select when connectingwin32_select
When doing a nonblocking connect() on win32, select() reports failure using
exceptfds instead of writefds. Allow this narrow case when doing a non-blocking
connect on Win32.
See:
https://msdn.microsoft.com/en-us/library/windows/desktop/ms740141(v=vs.85).aspx
Fixes #297
-rw-r--r-- | librabbitmq/amqp_socket.c | 31 | ||||
-rw-r--r-- | librabbitmq/amqp_socket.h | 3 |
2 files changed, 25 insertions, 9 deletions
diff --git a/librabbitmq/amqp_socket.c b/librabbitmq/amqp_socket.c index b60573f..f275816 100644 --- a/librabbitmq/amqp_socket.c +++ b/librabbitmq/amqp_socket.c @@ -303,27 +303,40 @@ start_poll: return AMQP_STATUS_OK; #elif defined(HAVE_SELECT) fd_set fds; + fd_set exceptfds; + fd_set *exceptfdsp; int res; struct timeval tv; struct timeval *tvp; - assert(event == AMQP_SF_POLLIN || event == AMQP_SF_POLLOUT); + assert((0 != (event & AMQP_SF_POLLIN)) || (0 != (event & AMQP_SF_POLLOUT))); +#ifndef _WIN32 + /* On Win32 connect() failure is indicated through the exceptfds, it does not + * make any sense to allow POLLERR on any other platform or condition */ + assert(0 == event & AMQP_SF_POLLERR); +#endif start_select: FD_ZERO(&fds); FD_SET(fd, &fds); + if (event & AMQP_SF_POLLERR) { + FD_ZERO(&exceptfds); + FD_SET(fd, &exceptfds); + exceptfdsp = &exceptfds; + } else { + exceptfdsp = NULL; + } + res = amqp_time_tv_until(deadline, &tv, &tvp); if (res != AMQP_STATUS_OK) { return res; } - switch (event) { - case AMQP_SF_POLLIN: - res = select(fd + 1, &fds, NULL, NULL, tvp); - break; - case AMQP_SF_POLLOUT: - res = select(fd + 1, NULL, &fds, NULL, tvp); + if (event & AMQP_SF_POLLIN) { + res = select(fd + 1, &fds, NULL, exceptfdsp, tvp); + } else if (event & AMQP_SF_POLLOUT) { + res = select(fd + 1, NULL, &fds, exceptfdsp, tvp); } if (0 < res) { @@ -481,10 +494,12 @@ int amqp_open_socket_inner(char const *hostname, #ifdef _WIN32 if (WSAEWOULDBLOCK == amqp_os_socket_error()) { + int event = AMQP_SF_POLLOUT | AMQP_SF_POLLERR; #else if (EINPROGRESS == amqp_os_socket_error()) { + int event = AMQP_SF_POLLOUT; #endif - last_error = amqp_poll(sockfd, AMQP_SF_POLLOUT, deadline); + last_error = amqp_poll(sockfd, event, deadline); if (AMQP_STATUS_OK == last_error) { int result; socklen_t result_len = sizeof(result); diff --git a/librabbitmq/amqp_socket.h b/librabbitmq/amqp_socket.h index 86183ec..e7c6e24 100644 --- a/librabbitmq/amqp_socket.h +++ b/librabbitmq/amqp_socket.h @@ -41,7 +41,8 @@ typedef enum { AMQP_SF_NONE = 0, AMQP_SF_MORE = 1, AMQP_SF_POLLIN = 2, - AMQP_SF_POLLOUT = 4 + AMQP_SF_POLLOUT = 4, + AMQP_SF_POLLERR = 8 } amqp_socket_flag_enum; int |