8000 posix: introduce p_poll emulation with select · libgit2/libgit2@1a44ace · GitHub
[go: up one dir, main page]

Skip to content

Commit 1a44ace

Browse files
committed
posix: introduce p_poll emulation with select
Not all systems have poll(2); emulate it with select(2).
1 parent 8e90505 commit 1a44ace

File tree

5 files changed

+85
-5
lines changed

5 files changed

+85
-5
lines changed

src/CMakeLists.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ check_prototype_definition_safe(qsort_s
8787
check_function_exists(getentropy GIT_RAND_GETENTROPY)
8888
check_function_exists(getloadavg GIT_RAND_GETLOADAVG)
8989

90+
# poll
91+
92+
check_symbol_exists(poll poll.h GIT_IO_POLL)
93+
check_symbol_exists(select sys/select.h GIT_IO_SELECT)
94+
9095
# determine architecture of the machine
9196

9297
if(CMAKE_SIZEOF_VOID_P EQUAL 8)

src/libgit2/streams/socket.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
# include <netdb.h>
2121
# include <netinet/in.h>
2222
# include <arpa/inet.h>
23-
# include <poll.h>
2423
#else
2524
# include <winsock2.h>
2625
# include <ws2tcpip.h>
@@ -135,13 +134,13 @@ static int connect_with_timeout(
135134
fd.events = POLLOUT;
136135
fd.revents = 0;
137136

138-
error = poll(&fd, 1, timeout);
137+
error = p_poll(&fd, 1, timeout);
139138

140139
if (error == 0) {
141140
return GIT_TIMEOUT;
142141
} else if (error != 1) {
143142
return -1;
144-
} else if ((fd.revents & (POLLHUP | POLLERR))) {
143+
} else if ((fd.revents & (POLLPRI | POLLHUP | POLLERR))) {
145144
return handle_sockerr(socket);
146145
} else if ((fd.revents & POLLOUT) != POLLOUT) {
147146
git_error_set(GIT_ERROR_NET,
@@ -236,7 +235,7 @@ static ssize_t socket_write(
236235
fd.events = POLLOUT;
237236
fd.revents = 0;
238237

239-
ret = poll(&fd, 1, st->parent.timeout);
238+
ret = p_poll(&fd, 1, st->parent.timeout);
240239

241240
if (ret == 1) {
242241
ret = p_send(st->s, data, len, 0);
@@ -272,7 +271,7 @@ static ssize_t socket_read(
272271
fd.events = POLLIN;
273272
fd.revents = 0;
274273

275-
ret = poll(&fd, 1, st->parent.timeout);
274+
ret = p_poll(&fd, 1, st->parent.timeout);
276275

277276
if (ret == 1) {
278277
ret = p_recv(st->s, data, len, 0);

src/util/git2_features.h.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,4 +61,7 @@
6161
#cmakedefine GIT_RAND_GETENTROPY 1
6262
#cmakedefine GIT_RAND_GETLOADAVG 1
6363

64+
#cmakedefine GIT_IO_POLL 1
65+
#cmakedefine GIT_IO_SELECT 1
66+
6467
#endif

src/util/posix.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,57 @@ int p_munmap(git_map *map)
301301
}
302302

303303
#endif
304+
305+
#if defined(GIT_IO_POLL) || defined(GIT_IO_WSAPOLL)
306+
307+
/* Handled by posix.h; this test simplifies the final else */
308+
309+
#elif defined(GIT_IO_SELECT)
310+
311+
int p_poll(struct pollfd *fds, unsigned int nfds, int timeout_ms)
312+
{
313+
fd_set read_fds, write_fds, except_fds;
314+
struct timeval timeout = { 0, 0 };
315+
unsigned int i;
316+
int max_fd = -1, ret;
317+
318+
FD_ZERO(&read_fds);
319+
FD_ZERO(&write_fds);
320+
FD_ZERO(&except_fds);
321+
322+
for (i = 0; i < nfds; i++) {
323+
if ((fds[i].events & POLLIN))
324+
FD_SET(fds[i].fd, &read_fds);
325+
326+
if ((fds[i].events & POLLOUT))
327+
FD_SET(fds[i].fd, &write_fds);
328+
329+
if ((fds[i].events & POLLPRI))
330+
FD_SET(fds[i].fd, &except_fds);
331+
332+
max_fd = MAX(max_fd, fds[i].fd);
333+
}
334+
335+
if (timeout_ms > 0) {
336+
timeout.tv_sec = timeout_ms / 1000;
337+
timeout.tv_usec = (timeout_ms % 1000) * 1000;
338+
}
339+
340+
if ((ret = select(max_fd + 1, &read_fds, &write_fds, &except_fds,
341+
timeout_ms < 0 ? NULL : &timeout)) < 0)
342+
goto done;
343+
344+
for (i = 0; i < nfds; i++) {
345+
fds[i].revents = 0 |
346+
FD_ISSET(fds[i].fd, &read_fds) ? POLLIN : 0 |
347+
FD_ISSET(fds[i].fd, &write_fds) ? POLLOUT : 0 |
348+
FD_ISSET(fds[i].fd, &except_fds) ? POLLPRI : 0;
349+
}
350+
351+
done:
352+
return ret;
353+
}
354+
355+
#else
356+
# error no poll compatible implementation
357+
#endif

src/util/posix.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,4 +195,23 @@ extern const char *p_gai_strerror(int ret);
195195
# define p_gai_strerror(c) gai_strerror(c)
196196
#endif /* NO_ADDRINFO */
197197

198+
#ifdef GIT_IO_POLL
199+
# include <poll.h>
200+
# define p_poll poll
201+
#else
202+
# define POLLIN 0x01
203+
# define POLLPRI 0x02
204+
# define POLLOUT 0x04
205+
# define POLLERR 0x08
206+
# define POLLHUP 0x10
207+
208+
struct pollfd {
209+
int fd;
210+
short events;
211+
short revents;
212+
};
213+
214+
extern int p_poll(struct pollfd *fds, unsigned int nfds, int timeout);
215+
#endif
216+
198217
#endif

0 commit comments

Comments
 (0)
0