_libssh2_wait_socket: fix timeouts for poll() uses
This commit is contained in:
parent
81d53de4dc
commit
9a24b03402
143
src/session.c
143
src/session.c
@ -549,6 +549,8 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
|
|||||||
int seconds_to_next;
|
int seconds_to_next;
|
||||||
int dir;
|
int dir;
|
||||||
int has_timeout;
|
int has_timeout;
|
||||||
|
long ms_to_next = 0;
|
||||||
|
long elapsed_ms;
|
||||||
|
|
||||||
/* since libssh2 often sets EAGAIN internally before this function is
|
/* since libssh2 often sets EAGAIN internally before this function is
|
||||||
called, we can decrease some amount of confusion in user programs by
|
called, we can decrease some amount of confusion in user programs by
|
||||||
@ -559,81 +561,82 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
|
|||||||
rc = libssh2_keepalive_send (session, &seconds_to_next);
|
rc = libssh2_keepalive_send (session, &seconds_to_next);
|
||||||
if (rc < 0)
|
if (rc < 0)
|
||||||
return rc;
|
return rc;
|
||||||
else {
|
|
||||||
/* figure out what to wait for */
|
|
||||||
dir = libssh2_session_block_directions(session);
|
|
||||||
|
|
||||||
if(!dir) {
|
ms_to_next = seconds_to_next * 1000;
|
||||||
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
|
||||||
"Nothing to wait for in wait_socket");
|
|
||||||
/* To avoid that we hang below just because there's nothing set to
|
|
||||||
wait for, we timeout on 1 second to also avoid busy-looping
|
|
||||||
during this condition */
|
|
||||||
seconds_to_next = 1;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
#ifdef HAVE_POLL
|
|
||||||
struct pollfd sockets[1];
|
|
||||||
|
|
||||||
sockets[0].fd = session->socket_fd;
|
/* figure out what to wait for */
|
||||||
sockets[0].events = 0;
|
dir = libssh2_session_block_directions(session);
|
||||||
sockets[0].revents = 0;
|
|
||||||
|
|
||||||
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
|
if(!dir) {
|
||||||
sockets[0].events |= POLLIN;
|
_libssh2_debug(session, LIBSSH2_TRACE_SOCKET,
|
||||||
|
"Nothing to wait for in wait_socket");
|
||||||
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
|
/* To avoid that we hang below just because there's nothing set to
|
||||||
sockets[0].events |= POLLOUT;
|
wait for, we timeout on 1 second to also avoid busy-looping
|
||||||
|
during this condition */
|
||||||
rc = poll(sockets, 1, seconds_to_next ?
|
ms_to_next = 1000;
|
||||||
seconds_to_next * 1000 : -1);
|
|
||||||
#else
|
|
||||||
fd_set rfd;
|
|
||||||
fd_set wfd;
|
|
||||||
fd_set *writefd = NULL;
|
|
||||||
fd_set *readfd = NULL;
|
|
||||||
struct timeval tv;
|
|
||||||
|
|
||||||
if (session->api_timeout > 0 &&
|
|
||||||
(seconds_to_next == 0 ||
|
|
||||||
seconds_to_next > session->api_timeout)) {
|
|
||||||
time_t now = time (NULL);
|
|
||||||
long elapsed_ms = (long)(1000*difftime(start_time, now));
|
|
||||||
if (elapsed_ms > session->api_timeout) {
|
|
||||||
session->err_code = LIBSSH2_ERROR_TIMEOUT;
|
|
||||||
return LIBSSH2_ERROR_TIMEOUT;
|
|
||||||
}
|
|
||||||
tv.tv_sec = (session->api_timeout - elapsed_ms) / 1000;
|
|
||||||
tv.tv_usec = ((session->api_timeout - elapsed_ms) % 1000) *
|
|
||||||
1000;
|
|
||||||
has_timeout = 1;
|
|
||||||
}
|
|
||||||
else if (seconds_to_next > 0) {
|
|
||||||
tv.tv_sec = seconds_to_next;
|
|
||||||
tv.tv_usec = 0;
|
|
||||||
has_timeout = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
has_timeout = 0;
|
|
||||||
|
|
||||||
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) {
|
|
||||||
FD_ZERO(&rfd);
|
|
||||||
FD_SET(session->socket_fd, &rfd);
|
|
||||||
readfd = &rfd;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) {
|
|
||||||
FD_ZERO(&wfd);
|
|
||||||
FD_SET(session->socket_fd, &wfd);
|
|
||||||
writefd = &wfd;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc = select(session->socket_fd + 1, readfd, writefd, NULL,
|
|
||||||
has_timeout ? &tv : NULL);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (session->api_timeout > 0 &&
|
||||||
|
(seconds_to_next == 0 ||
|
||||||
|
seconds_to_next > session->api_timeout)) {
|
||||||
|
time_t now = time (NULL);
|
||||||
|
elapsed_ms = (long)(1000*difftime(start_time, now));
|
||||||
|
if (elapsed_ms > session->api_timeout) {
|
||||||
|
session->err_code = LIBSSH2_ERROR_TIMEOUT;
|
||||||
|
return LIBSSH2_ERROR_TIMEOUT;
|
||||||
|
}
|
||||||
|
ms_to_next = (session->api_timeout - elapsed_ms);
|
||||||
|
has_timeout = 1;
|
||||||
|
}
|
||||||
|
else if (ms_to_next > 0) {
|
||||||
|
has_timeout = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
has_timeout = 0;
|
||||||
|
|
||||||
|
#ifdef HAVE_POLL
|
||||||
|
{
|
||||||
|
struct pollfd sockets[1];
|
||||||
|
|
||||||
|
sockets[0].fd = session->socket_fd;
|
||||||
|
sockets[0].events = 0;
|
||||||
|
sockets[0].revents = 0;
|
||||||
|
|
||||||
|
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
|
||||||
|
sockets[0].events |= POLLIN;
|
||||||
|
|
||||||
|
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
|
||||||
|
sockets[0].events |= POLLOUT;
|
||||||
|
|
||||||
|
rc = poll(sockets, 1, has_timeout?ms_to_next: -1);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
{
|
||||||
|
fd_set rfd;
|
||||||
|
fd_set wfd;
|
||||||
|
fd_set *writefd = NULL;
|
||||||
|
fd_set *readfd = NULL;
|
||||||
|
struct timeval tv;
|
||||||
|
|
||||||
|
tv.tv_sec = ms_to_next / 1000;
|
||||||
|
tv.tv_usec = (ms_to_next - tv.tv_sec*1000) * 1000;
|
||||||
|
|
||||||
|
if(dir & LIBSSH2_SESSION_BLOCK_INBOUND) {
|
||||||
|
FD_ZERO(&rfd);
|
||||||
|
FD_SET(session->socket_fd, &rfd);
|
||||||
|
readfd = &rfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) {
|
||||||
|
FD_ZERO(&wfd);
|
||||||
|
FD_SET(session->socket_fd, &wfd);
|
||||||
|
writefd = &wfd;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = select(session->socket_fd + 1, readfd, writefd, NULL,
|
||||||
|
has_timeout ? &tv : NULL);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if(rc <= 0) {
|
if(rc <= 0) {
|
||||||
/* timeout (or error), bail out with a timeout error */
|
/* timeout (or error), bail out with a timeout error */
|
||||||
session->err_code = LIBSSH2_ERROR_TIMEOUT;
|
session->err_code = LIBSSH2_ERROR_TIMEOUT;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user