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

Reply via email to