Commit 94f98400 by Edward Thomson

posix: introduce p_poll emulation with select

Not all systems have poll(2); emulate it with select(2).
parent fad90428
...@@ -87,6 +87,11 @@ check_prototype_definition_safe(qsort_s ...@@ -87,6 +87,11 @@ check_prototype_definition_safe(qsort_s
check_function_exists(getentropy GIT_RAND_GETENTROPY) check_function_exists(getentropy GIT_RAND_GETENTROPY)
check_function_exists(getloadavg GIT_RAND_GETLOADAVG) check_function_exists(getloadavg GIT_RAND_GETLOADAVG)
# poll
check_symbol_exists(poll poll.h GIT_IO_POLL)
check_symbol_exists(select sys/select.h GIT_IO_SELECT)
# determine architecture of the machine # determine architecture of the machine
if(CMAKE_SIZEOF_VOID_P EQUAL 8) if(CMAKE_SIZEOF_VOID_P EQUAL 8)
......
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
# include <netdb.h> # include <netdb.h>
# include <netinet/in.h> # include <netinet/in.h>
# include <arpa/inet.h> # include <arpa/inet.h>
# include <poll.h>
#else #else
# include <winsock2.h> # include <winsock2.h>
# include <ws2tcpip.h> # include <ws2tcpip.h>
...@@ -135,13 +134,13 @@ static int connect_with_timeout( ...@@ -135,13 +134,13 @@ static int connect_with_timeout(
fd.events = POLLOUT; fd.events = POLLOUT;
fd.revents = 0; fd.revents = 0;
error = poll(&fd, 1, timeout); error = p_poll(&fd, 1, timeout);
if (error == 0) { if (error == 0) {
return GIT_TIMEOUT; return GIT_TIMEOUT;
} else if (error != 1) { } else if (error != 1) {
return -1; return -1;
} else if ((fd.revents & (POLLHUP | POLLERR))) { } else if ((fd.revents & (POLLPRI | POLLHUP | POLLERR))) {
return handle_sockerr(socket); return handle_sockerr(socket);
} else if ((fd.revents & POLLOUT) != POLLOUT) { } else if ((fd.revents & POLLOUT) != POLLOUT) {
git_error_set(GIT_ERROR_NET, git_error_set(GIT_ERROR_NET,
...@@ -236,7 +235,7 @@ static ssize_t socket_write( ...@@ -236,7 +235,7 @@ static ssize_t socket_write(
fd.events = POLLOUT; fd.events = POLLOUT;
fd.revents = 0; fd.revents = 0;
ret = poll(&fd, 1, st->parent.timeout); ret = p_poll(&fd, 1, st->parent.timeout);
if (ret == 1) { if (ret == 1) {
ret = p_send(st->s, data, len, 0); ret = p_send(st->s, data, len, 0);
...@@ -272,7 +271,7 @@ static ssize_t socket_read( ...@@ -272,7 +271,7 @@ static ssize_t socket_read(
fd.events = POLLIN; fd.events = POLLIN;
fd.revents = 0; fd.revents = 0;
ret = poll(&fd, 1, st->parent.timeout); ret = p_poll(&fd, 1, st->parent.timeout);
if (ret == 1) { if (ret == 1) {
ret = p_recv(st->s, data, len, 0); ret = p_recv(st->s, data, len, 0);
......
...@@ -61,4 +61,7 @@ ...@@ -61,4 +61,7 @@
#cmakedefine GIT_RAND_GETENTROPY 1 #cmakedefine GIT_RAND_GETENTROPY 1
#cmakedefine GIT_RAND_GETLOADAVG 1 #cmakedefine GIT_RAND_GETLOADAVG 1
#cmakedefine GIT_IO_POLL 1
#cmakedefine GIT_IO_SELECT 1
#endif #endif
...@@ -301,3 +301,57 @@ int p_munmap(git_map *map) ...@@ -301,3 +301,57 @@ int p_munmap(git_map *map)
} }
#endif #endif
#if defined(GIT_IO_POLL) || defined(GIT_IO_WSAPOLL)
/* Handled by posix.h; this test simplifies the final else */
#elif defined(GIT_IO_SELECT)
int p_poll(struct pollfd *fds, unsigned int nfds, int timeout_ms)
{
fd_set read_fds, write_fds, except_fds;
struct timeval timeout = { 0, 0 };
unsigned int i;
int max_fd = -1, ret;
FD_ZERO(&read_fds);
FD_ZERO(&write_fds);
FD_ZERO(&except_fds);
for (i = 0; i < nfds; i++) {
if ((fds[i].events & POLLIN))
FD_SET(fds[i].fd, &read_fds);
if ((fds[i].events & POLLOUT))
FD_SET(fds[i].fd, &write_fds);
if ((fds[i].events & POLLPRI))
FD_SET(fds[i].fd, &except_fds);
max_fd = MAX(max_fd, fds[i].fd);
}
if (timeout_ms > 0) {
timeout.tv_sec = timeout_ms / 1000;
timeout.tv_usec = (timeout_ms % 1000) * 1000;
}
if ((ret = select(max_fd + 1, &read_fds, &write_fds, &except_fds,
timeout_ms < 0 ? NULL : &timeout)) < 0)
goto done;
for (i = 0; i < nfds; i++) {
fds[i].revents = 0 |
FD_ISSET(fds[i].fd, &read_fds) ? POLLIN : 0 |
FD_ISSET(fds[i].fd, &write_fds) ? POLLOUT : 0 |
FD_ISSET(fds[i].fd, &except_fds) ? POLLPRI : 0;
}
done:
return ret;
}
#else
# error no poll compatible implementation
#endif
...@@ -195,4 +195,23 @@ extern const char *p_gai_strerror(int ret); ...@@ -195,4 +195,23 @@ extern const char *p_gai_strerror(int ret);
# define p_gai_strerror(c) gai_strerror(c) # define p_gai_strerror(c) gai_strerror(c)
#endif /* NO_ADDRINFO */ #endif /* NO_ADDRINFO */
#ifdef GIT_IO_POLL
# include <poll.h>
# define p_poll poll
#else
# define POLLIN 0x01
# define POLLPRI 0x02
# define POLLOUT 0x04
# define POLLERR 0x08
# define POLLHUP 0x10
struct pollfd {
int fd;
short events;
short revents;
};
extern int p_poll(struct pollfd *fds, unsigned int nfds, int timeout);
#endif
#endif #endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment