summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Antonuk <alan.antonuk@gmail.com>2015-10-13 20:40:44 -0700
committerAlan Antonuk <alan.antonuk@gmail.com>2015-10-13 23:02:50 -0700
commitba7c342a55e200d1f72b30d74df1591b0f72de49 (patch)
tree238fe5ba21cf1b4cb96e0552c9298ee44df3481c
parente65bb790f7334d347270b7e9a9b455bb1f5f3894 (diff)
downloadrabbitmq-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.c31
-rw-r--r--librabbitmq/amqp_socket.h3
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