On Tue, 31 May 2011, Daniel Stenberg wrote:
It just struck me today when browsing this code (again) that your fix
completely left out the majority of all users: those who use poll()...
Okay, I suggest a little massaging of the function like the attached patch to
make the timeout work the same way when libssh2 is built to use poll().
I'm interested in a review/feedback. If nobody finds anything upsetting I'll
push this in a day or two.
--
/ daniel.haxx.se
From a5def5276c5b56dde5aa009ccb63f7f5d53b85df Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <dan...@haxx.se>
Date: Tue, 31 May 2011 23:49:32 +0200
Subject: [PATCH] _libssh2_wait_socket: fix timeouts for poll() uses
---
src/session.c | 131 +++++++++++++++++++++++++++++----------------------------
1 files changed, 67 insertions(+), 64 deletions(-)
diff --git a/src/session.c b/src/session.c
index d371ff0..3cf92ec 100644
--- a/src/session.c
+++ b/src/session.c
@@ -549,6 +549,8 @@ int _libssh2_wait_socket(LIBSSH2_SESSION *session, time_t start_time)
int seconds_to_next;
int dir;
int has_timeout;
+ long ms_to_next = 0;
+ long elapsed_ms;
/* since libssh2 often sets EAGAIN internally before this function is
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);
if (rc < 0)
return rc;
- else {
- /* figure out what to wait for */
- dir = libssh2_session_block_directions(session);
- if(!dir) {
- _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;
+ ms_to_next = seconds_to_next * 1000;
+
+ /* figure out what to wait for */
+ dir = libssh2_session_block_directions(session);
+
+ if(!dir) {
+ _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 */
+ ms_to_next = 1000;
+ }
+
+ 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];
+ {
+ struct pollfd sockets[1];
- sockets[0].fd = session->socket_fd;
- sockets[0].events = 0;
- sockets[0].revents = 0;
+ 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_INBOUND)
+ sockets[0].events |= POLLIN;
- if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
- sockets[0].events |= POLLOUT;
+ if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
+ sockets[0].events |= POLLOUT;
- rc = poll(sockets, 1, seconds_to_next ?
- seconds_to_next * 1000 : -1);
+ 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;
-
- 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;
- }
+ {
+ 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;
+ }
- rc = select(session->socket_fd + 1, readfd, writefd, NULL,
- has_timeout ? &tv : NULL);
-#endif
+ 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) {
/* timeout (or error), bail out with a timeout error */
session->err_code = LIBSSH2_ERROR_TIMEOUT;
--
1.7.5.3
_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel