summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlan Antonuk <alan.antonuk@gmail.com>2015-06-01 23:38:08 -0700
committerAlan Antonuk <alan.antonuk@gmail.com>2015-06-01 23:50:27 -0700
commit6e9565c91fca092f69111a40fa56eabe41c60ff4 (patch)
treee0ad88f5fcc84c4afa4ef1a79eb88aa75e6213b2
parent3f0d7454a3c31464fa771879d9922880e86b4a17 (diff)
downloadrabbitmq-c-6e9565c91fca092f69111a40fa56eabe41c60ff4.tar.gz
Lib: add select()-based implementation of poll()
Add select() based poll() implementation for platforms that either support this better (Win32) or don't support poll().
-rw-r--r--CMakeLists.txt18
-rw-r--r--cmake/config.h.in4
-rw-r--r--configure.ac5
-rw-r--r--librabbitmq/amqp_socket.c53
-rw-r--r--m4/ax_have_poll.m472
-rw-r--r--m4/ax_have_select.m471
6 files changed, 218 insertions, 5 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3be7535..095805f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -120,6 +120,24 @@ else (WIN32)
endif (WIN32)
cmake_pop_check_state()
+cmake_push_check_state()
+set(CMAKE_REQUIRED_INCLUDES "poll.h")
+check_function_exists(poll HAVE_POLL)
+set(CMAKE_REQUIRED_INCLUDES )
+if (NOT HAVE_POLL)
+ if (WIN32)
+ set(HAVE_SELECT 1)
+ else()
+ set(CMAKE_REQUIRED_INCLUDES sys/select.h)
+ check_function_exists(select HAVE_SELECT)
+ set(CMAKE_REQUIRED_INCLUDES )
+ endif()
+ if (NOT HAVE_SELECT)
+ message(FATAL_ERROR "rabbitmq-c requires poll() or select() to be available")
+ endif()
+endif()
+cmake_pop_check_state()
+
check_library_exists(rt clock_gettime "time.h" CLOCK_GETTIME_NEEDS_LIBRT)
if (CLOCK_GETTIME_NEEDS_LIBRT)
set(LIBRT rt)
diff --git a/cmake/config.h.in b/cmake/config.h.in
index 7f3fa71..a7e5a2c 100644
--- a/cmake/config.h.in
+++ b/cmake/config.h.in
@@ -8,6 +8,10 @@
#cmakedefine HAVE_HTONLL
+#cmakedefine HAVE_SELECT
+
+#cmakedefine HAVE_POLL
+
#define AMQ_PLATFORM "@CMAKE_SYSTEM@"
#endif /* CONFIG_H */
diff --git a/configure.ac b/configure.ac
index 3b34d9b..d1781bd 100644
--- a/configure.ac
+++ b/configure.ac
@@ -124,6 +124,11 @@ AC_LINK_IFELSE(
]
)
+# Need poll() or select()
+AX_HAVE_POLL([AC_DEFINE([HAVE_POLL], [], ["Have poll()"])],
+ AX_HAVE_SELECT([AC_DEFINE([HAVE_SELECT], [], ["Have select()"])],
+ [AC_MSG_ERROR([rabbitmq-c needs poll() or select()])]))
+
# Configure SSL/TLS
AC_ARG_WITH([ssl],
[AS_HELP_STRING([--with-ssl=@<:@cyassl/gnutls/no/openssl/polarssl/yes@:>@],
diff --git a/librabbitmq/amqp_socket.c b/librabbitmq/amqp_socket.c
index 6267d23..c110765 100644
--- a/librabbitmq/amqp_socket.c
+++ b/librabbitmq/amqp_socket.c
@@ -67,18 +67,19 @@
# include <sys/types.h> /* On older BSD this must come before net includes */
# include <netinet/in.h>
# include <netinet/tcp.h>
+# ifdef HAVE_SELECT
+# include <sys/select.h>
+# endif
# include <sys/socket.h>
# include <netdb.h>
# include <sys/uio.h>
# include <fcntl.h>
-# include <poll.h>
+# ifdef HAVE_POLL
+# include <poll.h>
+# endif
# include <unistd.h>
#endif
-#ifdef _WIN32
-# define poll(fdarray, nfds, timeout) WSAPoll(fdarray, nfds, timeout)
-#endif
-
static int amqp_id_in_reply_list( amqp_method_number_t expected, amqp_method_number_t *list );
static int
@@ -258,6 +259,7 @@ amqp_socket_get_sockfd(amqp_socket_t *self)
}
int amqp_poll(int fd, int event, amqp_time_t deadline) {
+#ifdef HAVE_POLL
struct pollfd pfd;
int res;
int timeout_ms;
@@ -299,6 +301,47 @@ start_poll:
}
}
return AMQP_STATUS_OK;
+#elif defined(HAVE_SELECT)
+ fd_set fds;
+ int res;
+ struct timeval tv;
+ struct timeval *tvp;
+
+ assert(event == AMQP_SF_POLLIN || event == AMQP_SF_POLLOUT);
+
+start_select:
+ FD_ZERO(&fds);
+ FD_SET(fd, &fds);
+
+ 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 (0 < res) {
+ return AMQP_STATUS_OK;
+ } else if (0 == res) {
+ return AMQP_STATUS_TIMEOUT;
+ } else {
+ switch (amqp_os_socket_error()) {
+ case EINTR:
+ goto start_select;
+ default:
+ return AMQP_STATUS_SOCKET_ERROR;
+ }
+ }
+ return AMQP_STATUS_OK;
+#else
+# error "poll() or select() is needed to compile rabbitmq-c"
+#endif
}
static ssize_t do_poll(amqp_connection_state_t state, ssize_t res,
diff --git a/m4/ax_have_poll.m4 b/m4/ax_have_poll.m4
new file mode 100644
index 0000000..14d3d4b
--- /dev/null
+++ b/m4/ax_have_poll.m4
@@ -0,0 +1,72 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_have_poll.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_HAVE_POLL([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# AX_HAVE_PPOLL([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# DESCRIPTION
+#
+# This macro determines whether the system supports the poll I/O event
+# interface. A neat usage example would be:
+#
+# AX_HAVE_POLL(
+# [AX_CONFIG_FEATURE_ENABLE(poll)],
+# [AX_CONFIG_FEATURE_DISABLE(poll)])
+# AX_CONFIG_FEATURE(
+# [poll], [This platform supports poll(7)],
+# [HAVE_POLL], [This platform supports poll(7).])
+#
+# Some systems -- most notably Linux kernel 2.6.16 and later -- also have
+# the variant ppoll(). The availability of that function can be tested
+# with the second macro. Generally speaking, it is safe to assume that
+# AX_HAVE_POLL would succeed if AX_HAVE_PPOLL has, but not the other way
+# round.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Peter Simons <simons@cryp.to>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 7
+
+AC_DEFUN([AX_HAVE_POLL], [dnl
+ AC_MSG_CHECKING([for poll(2)])
+ AC_CACHE_VAL([ax_cv_have_poll], [dnl
+ AC_LINK_IFELSE([dnl
+ AC_LANG_PROGRAM(
+ [#include <poll.h>],
+ [int rc; rc = poll((struct pollfd *)(0), 0, 0);])],
+ [ax_cv_have_poll=yes],
+ [ax_cv_have_poll=no])])
+ AS_IF([test "${ax_cv_have_poll}" = "yes"],
+ [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])dnl
+
+AC_DEFUN([AX_HAVE_PPOLL], [dnl
+ AC_MSG_CHECKING([for ppoll(2)])
+ AC_CACHE_VAL([ax_cv_have_ppoll], [dnl
+ AC_LINK_IFELSE([dnl
+ AC_LANG_PROGRAM(
+ [dnl
+#include <poll.h>
+#include <signal.h>],
+ [dnl
+int rc;
+rc = poll((struct pollfd *)(0), 0, 0);
+rc = ppoll((struct pollfd *)(0), 0, (struct timespec const *)(0), (sigset_t const *)(0));])],
+ [ax_cv_have_ppoll=yes],
+ [ax_cv_have_ppoll=no])])
+ AS_IF([test "${ax_cv_have_ppoll}" = "yes"],
+ [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])
diff --git a/m4/ax_have_select.m4 b/m4/ax_have_select.m4
new file mode 100644
index 0000000..4024212
--- /dev/null
+++ b/m4/ax_have_select.m4
@@ -0,0 +1,71 @@
+# ===========================================================================
+# http://www.gnu.org/software/autoconf-archive/ax_have_select.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+# AX_HAVE_SELECT([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+# AX_HAVE_PSELECT([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# DESCRIPTION
+#
+# This macro determines whether the system supports the select I/O event
+# interface. A neat usage example would be:
+#
+# AX_HAVE_SELECT(
+# [AX_CONFIG_FEATURE_ENABLE(select)],
+# [AX_CONFIG_FEATURE_DISABLE(select)])
+# AX_CONFIG_FEATURE(
+# [select], [This platform supports select(7)],
+# [HAVE_SELECT], [This platform supports select(7).])
+#
+# Some systems also have the variant pselect(). The availability of that
+# function can be tested with the second macro. Generally speaking, it is
+# safe to assume that AX_HAVE_SELECT would succeed if AX_HAVE_SELECT_PWAIT
+# has, but not the other way round.
+#
+# LICENSE
+#
+# Copyright (c) 2009 Peter Simons <simons@cryp.to>
+#
+# Copying and distribution of this file, with or without modification, are
+# permitted in any medium without royalty provided the copyright notice
+# and this notice are preserved. This file is offered as-is, without any
+# warranty.
+
+#serial 7
+
+AC_DEFUN([AX_HAVE_SELECT], [dnl
+ AC_MSG_CHECKING([for select(2)])
+ AC_CACHE_VAL([ax_cv_have_select], [dnl
+ AC_LINK_IFELSE([dnl
+ AC_LANG_PROGRAM(
+ [#include <sys/select.h>],
+ [int rc; rc = select(0, (fd_set *)(0), (fd_set *)(0), (fd_set *)(0), (struct timeval *)(0));])],
+ [ax_cv_have_select=yes],
+ [ax_cv_have_select=no])])
+ AS_IF([test "${ax_cv_have_select}" = "yes"],
+ [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])dnl
+
+AC_DEFUN([AX_HAVE_PSELECT], [dnl
+ AC_MSG_CHECKING([for pselect(2)])
+ AC_CACHE_VAL([ax_cv_have_pselect], [dnl
+ AC_LINK_IFELSE([dnl
+ AC_LANG_PROGRAM(
+ [dnl
+#include <sys/select.h>
+#include <signal.h>],
+ [dnl
+int rc;
+rc = select(0, (fd_set *)(0), (fd_set *)(0), (fd_set *)(0), (struct timeval *)(0));
+rc = pselect(0, (fd_set *)(0), (fd_set *)(0), (fd_set *)(0), (struct timespec const *)(0), (sigset_t const *)(0));])],
+ [ax_cv_have_pselect=yes],
+ [ax_cv_have_pselect=no])])
+ AS_IF([test "${ax_cv_have_pselect}" = "yes"],
+ [AC_MSG_RESULT([yes])
+$1],[AC_MSG_RESULT([no])
+$2])
+])dnl