mirror of
https://github.com/moparisthebest/socat
synced 2024-12-22 06:58:47 -05:00
MacOSX port: xiopoll() uses Select(), except when too many fds
This commit is contained in:
parent
097608e8a9
commit
b0d29f8dc7
39
socat.c
39
socat.c
@ -664,7 +664,6 @@ int socat(const char *address1, const char *address2) {
|
|||||||
*/
|
*/
|
||||||
int childleftdata(xiofile_t *xfd) {
|
int childleftdata(xiofile_t *xfd) {
|
||||||
struct pollfd in;
|
struct pollfd in;
|
||||||
int timeout = 0; /* milliseconds */
|
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
/* have to check if a child process died before, but left read data */
|
/* have to check if a child process died before, but left read data */
|
||||||
@ -673,6 +672,7 @@ int childleftdata(xiofile_t *xfd) {
|
|||||||
XIO_RDSTREAM(xfd)->howtoend == END_CLOSE_KILL ||
|
XIO_RDSTREAM(xfd)->howtoend == END_CLOSE_KILL ||
|
||||||
XIO_RDSTREAM(xfd)->howtoend == END_SHUTDOWN_KILL) &&
|
XIO_RDSTREAM(xfd)->howtoend == END_SHUTDOWN_KILL) &&
|
||||||
XIO_RDSTREAM(xfd)->para.exec.pid == 0) {
|
XIO_RDSTREAM(xfd)->para.exec.pid == 0) {
|
||||||
|
struct timeval timeout = { 0, 0 };
|
||||||
|
|
||||||
if (XIO_READABLE(xfd) && !(XIO_RDSTREAM(xfd)->eof >= 2 && !XIO_RDSTREAM(xfd)->ignoreeof)) {
|
if (XIO_READABLE(xfd) && !(XIO_RDSTREAM(xfd)->eof >= 2 && !XIO_RDSTREAM(xfd)->ignoreeof)) {
|
||||||
in.fd = XIO_GETRDFD(xfd);
|
in.fd = XIO_GETRDFD(xfd);
|
||||||
@ -680,7 +680,7 @@ int childleftdata(xiofile_t *xfd) {
|
|||||||
in.revents = 0;
|
in.revents = 0;
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
retval = xiopoll(&in, 1, timeout);
|
retval = xiopoll(&in, 1, &timeout);
|
||||||
} while (retval < 0 && errno == EINTR);
|
} while (retval < 0 && errno == EINTR);
|
||||||
|
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
@ -767,7 +767,7 @@ int _socat(void) {
|
|||||||
XIO_GETRDFD(sock2), XIO_GETWRFD(sock2));
|
XIO_GETRDFD(sock2), XIO_GETWRFD(sock2));
|
||||||
while (XIO_RDSTREAM(sock1)->eof <= 1 ||
|
while (XIO_RDSTREAM(sock1)->eof <= 1 ||
|
||||||
XIO_RDSTREAM(sock2)->eof <= 1) {
|
XIO_RDSTREAM(sock2)->eof <= 1) {
|
||||||
int timeout;
|
struct timeval timeout, *to = NULL;
|
||||||
|
|
||||||
Debug6("data loop: sock1->eof=%d, sock2->eof=%d, closing=%d, wasaction=%d, total_to={"F_tv_sec"."F_tv_usec"}",
|
Debug6("data loop: sock1->eof=%d, sock2->eof=%d, closing=%d, wasaction=%d, total_to={"F_tv_sec"."F_tv_usec"}",
|
||||||
XIO_RDSTREAM(sock1)->eof, XIO_RDSTREAM(sock2)->eof,
|
XIO_RDSTREAM(sock1)->eof, XIO_RDSTREAM(sock2)->eof,
|
||||||
@ -799,21 +799,21 @@ int _socat(void) {
|
|||||||
|
|
||||||
if (polling) {
|
if (polling) {
|
||||||
/* there is a ignoreeof poll timeout, use it */
|
/* there is a ignoreeof poll timeout, use it */
|
||||||
timeout = 1000*socat_opts.pollintv.tv_sec +
|
timeout = socat_opts.pollintv;
|
||||||
socat_opts.pollintv.tv_usec/1000; /*!!! overflow?*/
|
to = &timeout;
|
||||||
} else if (socat_opts.total_timeout.tv_sec != 0 ||
|
} else if (socat_opts.total_timeout.tv_sec != 0 ||
|
||||||
socat_opts.total_timeout.tv_usec != 0) {
|
socat_opts.total_timeout.tv_usec != 0) {
|
||||||
/* there might occur a total inactivity timeout */
|
/* there might occur a total inactivity timeout */
|
||||||
timeout = 1000*socat_opts.total_timeout.tv_sec +
|
timeout = socat_opts.total_timeout;
|
||||||
socat_opts.total_timeout.tv_usec/1000;
|
to = &timeout;
|
||||||
} else {
|
} else {
|
||||||
timeout = -1; /* forever */
|
to = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (closing>=1) {
|
if (closing>=1) {
|
||||||
/* first eof already occurred, start end timer */
|
/* first eof already occurred, start end timer */
|
||||||
timeout = 1000*socat_opts.closwait.tv_sec +
|
timeout = socat_opts.pollintv;
|
||||||
socat_opts.closwait.tv_usec/1000;
|
to = &timeout;
|
||||||
closing = 2;
|
closing = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -826,17 +826,18 @@ int _socat(void) {
|
|||||||
|
|
||||||
if (closing>=1) {
|
if (closing>=1) {
|
||||||
/* first eof already occurred, start end timer */
|
/* first eof already occurred, start end timer */
|
||||||
timeout = 1000*socat_opts.closwait.tv_sec +
|
timeout = socat_opts.closwait;
|
||||||
socat_opts.closwait.tv_usec/1000;
|
to = &timeout;
|
||||||
closing = 2;
|
closing = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use the ignoreeof timeout if appropriate */
|
/* use the ignoreeof timeout if appropriate */
|
||||||
if (polling) {
|
if (polling) {
|
||||||
int ptimeout = 1000*socat_opts.pollintv.tv_sec +
|
if (closing == 0 ||
|
||||||
socat_opts.pollintv.tv_usec/1000;
|
(socat_opts.pollintv.tv_sec < timeout.tv_sec) ||
|
||||||
if (closing == 0 || ptimeout < timeout) {
|
((socat_opts.pollintv.tv_sec == timeout.tv_sec) &&
|
||||||
timeout = ptimeout;
|
socat_opts.pollintv.tv_usec < timeout.tv_usec)) {
|
||||||
|
timeout = socat_opts.pollintv;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -880,7 +881,7 @@ int _socat(void) {
|
|||||||
fd2in->fd = -1;
|
fd2in->fd = -1;
|
||||||
}
|
}
|
||||||
/* frame 0: innermost part of the transfer loop: check FD status */
|
/* frame 0: innermost part of the transfer loop: check FD status */
|
||||||
retval = xiopoll(fds, 4, timeout);
|
retval = xiopoll(fds, 4, to);
|
||||||
if (retval >= 0 || errno != EINTR) {
|
if (retval >= 0 || errno != EINTR) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -947,14 +948,14 @@ int _socat(void) {
|
|||||||
}
|
}
|
||||||
mayrd2 = true;
|
mayrd2 = true;
|
||||||
}
|
}
|
||||||
if (XIO_GETWRFD(sock1) >= 0 && (fd1out->revents)) {
|
if (XIO_GETWRFD(sock1) >= 0 && fd1out->fd >= 0 && fd1out->revents) {
|
||||||
if (fd1out->revents & POLLNVAL) {
|
if (fd1out->revents & POLLNVAL) {
|
||||||
Error1("poll(...[%d]: invalid request", fd1out->fd);
|
Error1("poll(...[%d]: invalid request", fd1out->fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
maywr1 = true;
|
maywr1 = true;
|
||||||
}
|
}
|
||||||
if (XIO_GETWRFD(sock2) >= 0 && (fd2out->revents)) {
|
if (XIO_GETWRFD(sock2) >= 0 && fd2out->fd >= 0 && fd2out->revents) {
|
||||||
if (fd2out->revents & POLLNVAL) {
|
if (fd2out->revents & POLLNVAL) {
|
||||||
Error1("poll(...[%d]: invalid request", fd2out->fd);
|
Error1("poll(...[%d]: invalid request", fd2out->fd);
|
||||||
return -1;
|
return -1;
|
||||||
|
50
sysutils.c
50
sysutils.c
@ -413,12 +413,56 @@ const char *hstrerror(int err) {
|
|||||||
|
|
||||||
/* this function behaves like poll(). It tries to do so even when the poll()
|
/* this function behaves like poll(). It tries to do so even when the poll()
|
||||||
system call is not available. */
|
system call is not available. */
|
||||||
int xiopoll(struct pollfd fds[], nfds_t nfds, int timeout) {
|
int xiopoll(struct pollfd fds[], nfds_t nfds, struct timeval *timeout) {
|
||||||
|
int i, n = 0;
|
||||||
|
int result = 0;
|
||||||
|
|
||||||
|
while (true) { /* should be if (), but we want to break */
|
||||||
|
fd_set readfds;
|
||||||
|
fd_set writefds;
|
||||||
|
fd_set exceptfds;
|
||||||
|
|
||||||
|
FD_ZERO(&readfds); FD_ZERO(&writefds); FD_ZERO(&exceptfds);
|
||||||
|
for (i = 0; i < nfds; ++i) {
|
||||||
|
fds[i].revents = 0;
|
||||||
|
if (fds[i].fd < 0) { continue; }
|
||||||
|
if (fds[i].fd > FD_SETSIZE) { break; /* use poll */ }
|
||||||
|
if (fds[i].events & POLLIN) {
|
||||||
|
FD_SET(fds[i].fd, &readfds); n = MAX(n, fds[i].fd); }
|
||||||
|
if (fds[i].events & POLLOUT) {
|
||||||
|
FD_SET(fds[i].fd, &writefds); n = MAX(n, fds[i].fd); }
|
||||||
|
}
|
||||||
|
if (fds[i].fd > FD_SETSIZE) { break; /* use poll */ }
|
||||||
|
|
||||||
|
result = Select(n+1, &readfds, &writefds, &exceptfds, timeout);
|
||||||
|
if (result < 0) { return result; }
|
||||||
|
for (i = 0; i < nfds; ++i) {
|
||||||
|
if (fds[i].fd < 0) { continue; }
|
||||||
|
if ((fds[i].events & POLLIN) && FD_ISSET(fds[i].fd, &readfds)) {
|
||||||
|
fds[i].revents |= POLLIN; ++result;
|
||||||
|
}
|
||||||
|
if ((fds[i].events & POLLOUT) && FD_ISSET(fds[i].fd, &writefds)) {
|
||||||
|
fds[i].revents |= POLLOUT; ++result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
#if HAVE_POLL
|
#if HAVE_POLL
|
||||||
return Poll(fds, nfds, timeout);
|
{
|
||||||
|
int ms = 0;
|
||||||
|
if (timeout == NULL) {
|
||||||
|
ms = -1;
|
||||||
|
} else {
|
||||||
|
ms = 1000*timeout->tv_sec + timeout->tv_usec/1000;
|
||||||
|
}
|
||||||
|
/*! timeout */
|
||||||
|
return Poll(fds, nfds, ms);
|
||||||
#else /* HAVE_POLL */
|
#else /* HAVE_POLL */
|
||||||
/*!!! wrap around Select() */
|
} else {
|
||||||
|
Error("poll() not available");
|
||||||
|
return -1;
|
||||||
#endif /* !HAVE_POLL */
|
#endif /* !HAVE_POLL */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -74,7 +74,7 @@ extern int getusergroups(const char *user, gid_t *list, size_t *ngroups);
|
|||||||
extern const char *hstrerror(int err);
|
extern const char *hstrerror(int err);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int xiopoll(struct pollfd fds[], nfds_t nfds, int timeout);
|
extern int xiopoll(struct pollfd fds[], nfds_t nfds, struct timeval *timeout);
|
||||||
|
|
||||||
extern int parseport(const char *portname, int proto);
|
extern int parseport(const char *portname, int proto);
|
||||||
|
|
||||||
|
2
test.sh
2
test.sh
@ -5697,6 +5697,7 @@ if ! feat=$(testaddrs pty); then
|
|||||||
$PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr a-z A-Z) not available${NORMAL}\n" $N
|
$PRINTF "test $F_n $TEST... ${YELLOW}$(echo $feat |tr a-z A-Z) not available${NORMAL}\n" $N
|
||||||
numCANT=$((numCANT+1))
|
numCANT=$((numCANT+1))
|
||||||
else
|
else
|
||||||
|
set -vx
|
||||||
SIG="$(signum $signam)"
|
SIG="$(signum $signam)"
|
||||||
te="$td/test$N.stderr"
|
te="$td/test$N.stderr"
|
||||||
tpp="$td/test$N.ppid"
|
tpp="$td/test$N.ppid"
|
||||||
@ -5725,6 +5726,7 @@ else
|
|||||||
numFAIL=$((numFAIL+1))
|
numFAIL=$((numFAIL+1))
|
||||||
fi
|
fi
|
||||||
wait
|
wait
|
||||||
|
set +vx
|
||||||
fi ;; # feat
|
fi ;; # feat
|
||||||
esac
|
esac
|
||||||
N=$((N+1))
|
N=$((N+1))
|
||||||
|
@ -840,18 +840,17 @@ int _xioopen_connect(struct single *xfd, struct sockaddr *us, size_t uslen,
|
|||||||
if (errno == EINPROGRESS) {
|
if (errno == EINPROGRESS) {
|
||||||
if (xfd->para.socket.connect_timeout.tv_sec != 0 ||
|
if (xfd->para.socket.connect_timeout.tv_sec != 0 ||
|
||||||
xfd->para.socket.connect_timeout.tv_usec != 0) {
|
xfd->para.socket.connect_timeout.tv_usec != 0) {
|
||||||
int timeout;
|
struct timeval timeout;
|
||||||
struct pollfd writefd;
|
struct pollfd writefd;
|
||||||
int result;
|
int result;
|
||||||
|
|
||||||
Info4("connect(%d, %s, "F_Zd"): %s",
|
Info4("connect(%d, %s, "F_Zd"): %s",
|
||||||
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
xfd->fd, sockaddr_info(them, themlen, infobuff, sizeof(infobuff)),
|
||||||
themlen, strerror(errno));
|
themlen, strerror(errno));
|
||||||
timeout = 1000*xfd->para.socket.connect_timeout.tv_sec +
|
timeout = xfd->para.socket.connect_timeout;
|
||||||
xfd->para.socket.connect_timeout.tv_usec/1000;
|
|
||||||
writefd.fd = xfd->fd;
|
writefd.fd = xfd->fd;
|
||||||
writefd.events = (POLLIN|POLLHUP|POLLERR);
|
writefd.events = (POLLIN|POLLHUP|POLLERR);
|
||||||
result = Poll(&writefd, 1, timeout);
|
result = xiopoll(&writefd, 1, &timeout);
|
||||||
if (result < 0) {
|
if (result < 0) {
|
||||||
Msg3(level, "poll({%d,POLLIN|POLLHUP|POLLER},,%d): %s",
|
Msg3(level, "poll({%d,POLLIN|POLLHUP|POLLER},,%d): %s",
|
||||||
xfd->fd, timeout, strerror(errno));
|
xfd->fd, timeout, strerror(errno));
|
||||||
@ -1319,7 +1318,7 @@ int _xioopen_dgram_recvfrom(struct single *xfd, int xioflags,
|
|||||||
}
|
}
|
||||||
readfd.fd = xfd->fd;
|
readfd.fd = xfd->fd;
|
||||||
readfd.events = POLLIN;
|
readfd.events = POLLIN;
|
||||||
if (Poll(&readfd, 1, -1) > 0) {
|
if (xiopoll(&readfd, 1, NULL) > 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ int xioopen_ipdgram_listen(int argc, const char *argv[], struct opt *opts,
|
|||||||
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
|
sockaddr_info(&us.soa, uslen, infobuff, sizeof(infobuff)));
|
||||||
readfd.fd = fd->stream.fd;
|
readfd.fd = fd->stream.fd;
|
||||||
readfd.events = POLLIN|POLLERR;
|
readfd.events = POLLIN|POLLERR;
|
||||||
while (Poll(&readfd, 1, -1) < 0) {
|
while (xiopoll(&readfd, 1, NULL) < 0) {
|
||||||
if (errno != EINTR) break;
|
if (errno != EINTR) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user