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
check_function_exists(getentropy GIT_RAND_GETENTROPY)
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
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
......
......@@ -20,7 +20,6 @@
# include <netdb.h>
# include <netinet/in.h>
# include <arpa/inet.h>
# include <poll.h>
#else
# include <winsock2.h>
# include <ws2tcpip.h>
......@@ -135,13 +134,13 @@ static int connect_with_timeout(
fd.events = POLLOUT;
fd.revents = 0;
error = poll(&fd, 1, timeout);
error = p_poll(&fd, 1, timeout);
if (error == 0) {
return GIT_TIMEOUT;
} else if (error != 1) {
return -1;
} else if ((fd.revents & (POLLHUP | POLLERR))) {
} else if ((fd.revents & (POLLPRI | POLLHUP | POLLERR))) {
return handle_sockerr(socket);
} else if ((fd.revents & POLLOUT) != POLLOUT) {
git_error_set(GIT_ERROR_NET,
......@@ -236,7 +235,7 @@ static ssize_t socket_write(
fd.events = POLLOUT;
fd.revents = 0;
ret = poll(&fd, 1, st->parent.timeout);
ret = p_poll(&fd, 1, st->parent.timeout);
if (ret == 1) {
ret = p_send(st->s, data, len, 0);
......@@ -272,7 +271,7 @@ static ssize_t socket_read(
fd.events = POLLIN;
fd.revents = 0;
ret = poll(&fd, 1, st->parent.timeout);
ret = p_poll(&fd, 1, st->parent.timeout);
if (ret == 1) {
ret = p_recv(st->s, data, len, 0);
......
......@@ -61,4 +61,7 @@
#cmakedefine GIT_RAND_GETENTROPY 1
#cmakedefine GIT_RAND_GETLOADAVG 1
#cmakedefine GIT_IO_POLL 1
#cmakedefine GIT_IO_SELECT 1
#endif
......@@ -301,3 +301,57 @@ int p_munmap(git_map *map)
}
#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);
# define p_gai_strerror(c) gai_strerror(c)
#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
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