Skip to content

Commit

Permalink
XmlRpcpp fixes for OSX (#1402)
Browse files Browse the repository at this point in the history
* Handle RLIM_INFINITY

* XmlRpcServer: use unsigned int for rlimit

* Properly link xmlrpcpp tests

* Exclude test libraries from all target

* Symbol overriding for OSX

* fix signed / unsigned comparison warning
  • Loading branch information
dirk-thomas committed Aug 9, 2018
1 parent 0463bc9 commit 7d860bb
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 20 deletions.
12 changes: 10 additions & 2 deletions utilities/xmlrpcpp/src/XmlRpcServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,15 +27,18 @@ XmlRpcServer::XmlRpcServer()
_accept_retry_time_sec(0.0)
{
struct rlimit limit = { .rlim_cur = 0, .rlim_max = 0 };
int max_files = 1024;
unsigned int max_files = 1024;

if(getrlimit(RLIMIT_NOFILE, &limit) == 0) {
max_files = limit.rlim_max;
if( limit.rlim_max == RLIM_INFINITY ) {
max_files = 0;
}
} else {
XmlRpcUtil::error("Could not get open file limit: %s", strerror(errno));
}
pollfds.resize(max_files);
for(int i=0; i<max_files; i++) {
for(unsigned int i=0; i<max_files; i++) {
// Set up file descriptor query for all events.
pollfds[i].fd = i;
pollfds[i].events = POLLIN | POLLPRI | POLLOUT;
Expand Down Expand Up @@ -218,6 +221,11 @@ int XmlRpcServer::countFreeFDs() {

// Get the current soft limit on the number of file descriptors.
if(getrlimit(RLIMIT_NOFILE, &limit) == 0) {
// If we have infinite file descriptors, always return FREE_FD_BUFFER so
// that we never hit the low-water mark.
if( limit.rlim_max == RLIM_INFINITY ) {
return FREE_FD_BUFFER;
}

// Poll the available file descriptors.
// The POSIX specification guarantees that rlim_cur will always be less or
Expand Down
29 changes: 23 additions & 6 deletions utilities/xmlrpcpp/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ find_package(Boost REQUIRED COMPONENTS system thread)
include_directories(${Boost_INCLUDE_DIRS})

add_library(test_fixtures test_fixtures.cpp)
target_link_libraries(test_fixtures ${Boost_LIBRARIES})
target_link_libraries(test_fixtures xmlrpcpp ${Boost_LIBRARIES} ${GTEST_LIBRARIES})
set_target_properties(test_fixtures PROPERTIES EXCLUDE_FROM_ALL TRUE)

catkin_add_gtest(HelloTest HelloTest.cpp)
target_link_libraries(HelloTest xmlrpcpp ${Boost_LIBRARIES})
Expand All @@ -24,6 +25,8 @@ catkin_add_gtest(test_ulimit test_ulimit.cpp)
target_link_libraries(test_ulimit xmlrpcpp test_fixtures ${Boost_LIBRARIES})

add_library(mock_socket mock_socket.cpp)
target_link_libraries(mock_socket ${GTEST_LIBRARIES})
set_target_properties(mock_socket PROPERTIES EXCLUDE_FROM_ALL TRUE)

catkin_add_gtest(test_client
test_client.cpp
Expand All @@ -46,10 +49,17 @@ catkin_add_gtest(test_dispatch
../libb64/src/cencode.c
)
target_link_libraries(test_dispatch mock_socket ${catkin_LIBRARIES})
if(APPLE)
set_target_properties(test_dispatch PROPERTIES
LINK_FLAGS
"-Wl,--wrap=select -Wl,--wrap=poll"
"-Wl,-alias,___wrap_poll,_poll"
)
elseif(UNIX)
set_target_properties(test_dispatch PROPERTIES
LINK_FLAGS
"-Wl,--wrap=poll"
)
endif()

if(NOT WIN32)
catkin_add_gtest(test_socket
Expand All @@ -58,10 +68,17 @@ if(NOT WIN32)
../src/XmlRpcSocket.cpp
../src/XmlRpcUtil.cpp
)
set_target_properties(test_socket PROPERTIES
LINK_FLAGS
"-Wl,--wrap=accept -Wl,--wrap=bind -Wl,--wrap=close -Wl,--wrap=connect -Wl,--wrap=getaddrinfo -Wl,--wrap=getsockname -Wl,--wrap=listen -Wl,--wrap=read -Wl,--wrap=setsockopt -Wl,--wrap=select -Wl,--wrap=socket -Wl,--wrap=write -Wl,--wrap=fcntl -Wl,--wrap=freeaddrinfo"
)
if(APPLE)
set_target_properties(test_socket PROPERTIES
LINK_FLAGS
"-Wl,-alias,___wrap_accept,_accept -Wl,-alias,___wrap_bind,_bind -Wl,-alias,___wrap_close,_close -Wl,-alias,___wrap_connect,_connect -Wl,-alias,___wrap_getaddrinfo,_getaddrinfo -Wl,-alias,___wrap_getsockname,_getsockname -Wl,-alias,___wrap_listen,_listen -Wl,-alias,___wrap_read,_read -Wl,-alias,___wrap_setsockopt,_setsockopt -Wl,-alias,___wrap_select,_select -Wl,-alias,___wrap_select,_select$1050 -Wl,-alias,___wrap_socket,_socket -Wl,-alias,___wrap_write,_write -Wl,-alias,___wrap_fcntl,_fcntl -Wl,-alias,___wrap_freeaddrinfo,_freeaddrinfo"
)
elseif(UNIX)
set_target_properties(test_socket PROPERTIES
LINK_FLAGS
"-Wl,--wrap=accept -Wl,--wrap=bind -Wl,--wrap=close -Wl,--wrap=connect -Wl,--wrap=getaddrinfo -Wl,--wrap=getsockname -Wl,--wrap=listen -Wl,--wrap=read -Wl,--wrap=setsockopt -Wl,--wrap=select -Wl,--wrap=socket -Wl,--wrap=write -Wl,--wrap=fcntl -Wl,--wrap=freeaddrinfo"
)
endif()
endif()

catkin_add_gtest(TestValues TestValues.cpp)
Expand Down
4 changes: 2 additions & 2 deletions utilities/xmlrpcpp/test/mock_socket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ std::string XmlRpcSocket::getErrorMsg(int error) {
std::deque<int> close_calls;
void XmlRpcSocket::close(int fd) {
EXPECT_LE(1, close_calls.size());
EXPECT_LE(1u, close_calls.size());
if (close_calls.size() > 0) {
int close_fd = close_calls.front();
close_calls.pop_front();
Expand Down Expand Up @@ -299,7 +299,7 @@ void MockSocketTest::TearDown() {
void MockSocketTest::CheckCalls() {
// Check that call counters and queues are empty.
EXPECT_EQ(0, socket_calls);
EXPECT_EQ(0, close_calls.size());
EXPECT_EQ(0u, close_calls.size());
EXPECT_EQ(0, setNonBlocking_calls);
EXPECT_EQ(0, setReuseAddr_calls);
EXPECT_EQ(0, bind_calls);
Expand Down
6 changes: 2 additions & 4 deletions utilities/xmlrpcpp/test/test_dispatch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,13 @@
// those symbols instead use __wrap_xxx
extern "C" {
// Mock for poll
int __real_poll(struct pollfd *fds, nfds_t nfds, int timeout);

int (*fake_poll)(struct pollfd *, nfds_t, int) = 0;

int __wrap_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
if(fake_poll) {
return fake_poll(fds, nfds, timeout);
} else {
return __real_poll(fds, nfds, timeout);
return 0;
}
}

Expand All @@ -72,7 +70,7 @@ int mock_poll(struct pollfd *fds, nfds_t nfds, int timeout) {
EXPECT_EQ(poll_fds.size(), nfds);
EXPECT_EQ(poll_timeout, timeout);

for(nfds_t i=0; i<std::min(nfds, poll_fds.size()); i++) {
for(nfds_t i=0; i<nfds && i<poll_fds.size(); i++) {
EXPECT_EQ(poll_fds[i].fd, fds[i].fd);
EXPECT_EQ(poll_fds[i].events, fds[i].events);
fds[i].revents = poll_fds[i].revents;
Expand Down
9 changes: 3 additions & 6 deletions utilities/xmlrpcpp/test/test_system_mocks.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@
#endif

#define MOCK_SYSCALL(ret, name, ARG_TYPES, ARG_NAMES) \
ret __real_##name ARG_TYPES; \
ret(*fake_##name) ARG_TYPES = 0; \
ret __wrap_##name ARG_TYPES { \
if (fake_##name) { \
return fake_##name ARG_NAMES; \
} else { \
return __real_##name ARG_NAMES; \
return -1; \
} \
} \
int name##_calls = 0; \
Expand All @@ -47,7 +46,6 @@

// custom mock for fcntl because it is varargs
// the mocked version always takes the third argument
int __real_fcntl(int fd, int cmd, ...);
int (*fake_fcntl)(int fd, int cmd, unsigned long) = 0;
int __wrap_fcntl(int fd, int cmd, ...) {
va_list ap;
Expand All @@ -58,7 +56,7 @@ int __wrap_fcntl(int fd, int cmd, ...) {
if (fake_fcntl) {
return fake_fcntl(fd, cmd, arg);
} else {
return __real_fcntl(fd, cmd, arg);
return -1;
}
}
int fcntl_calls = 0;
Expand All @@ -68,13 +66,12 @@ int count_fcntl(int fd, int cmd, unsigned long arg) {
}

// Custom mock for freeaddrinfo because it returns void.
void __real_freeaddrinfo(struct addrinfo* res);
void (*fake_freeaddrinfo)(struct addrinfo* res) = 0;
void __wrap_freeaddrinfo(struct addrinfo* res) {
if (fake_freeaddrinfo) {
return fake_freeaddrinfo(res);
} else {
return __real_freeaddrinfo(res);
return;
}
}
int freeaddrinfo_calls = 0;
Expand Down

0 comments on commit 7d860bb

Please sign in to comment.