]> granicus.if.org Git - curl/commitdiff
ssh: loop the state machine if not done and not blocking
authorDaniel Stenberg <daniel@haxx.se>
Mon, 4 Mar 2019 15:17:10 +0000 (16:17 +0100)
committerDaniel Stenberg <daniel@haxx.se>
Tue, 5 Mar 2019 06:57:11 +0000 (07:57 +0100)
If the state machine isn't complete, didn't fail and it didn't return
due to blocking it can just as well loop again.

This addresses the problem with SFTP directory listings where we would
otherwise return back to the parent and as the multi state machine
doesn't have any code for using CURLM_CALL_MULTI_PERFORM for as long the
doing phase isn't complete, it would return out when in reality there
was more data to deal with.

Fixes #3506
Closes #3644

lib/ssh.c

index b3583126989ccade277b90458dc01e5cac9cccba..46f52eceb03d55cb681c65efc5206d7307ccb2d2 100644 (file)
--- a/lib/ssh.c
+++ b/lib/ssh.c
 #include "multiif.h"
 #include "select.h"
 #include "warnless.h"
+#include "curl_path.h"
 
 /* The last 3 #include files should be in this order */
 #include "curl_printf.h"
 #include "curl_memory.h"
-#include "curl_path.h"
 #include "memdebug.h"
 
 #if LIBSSH2_VERSION_NUM >= 0x010206
@@ -2789,9 +2789,12 @@ static CURLcode ssh_multi_statemach(struct connectdata *conn, bool *done)
   CURLcode result = CURLE_OK;
   bool block; /* we store the status and use that to provide a ssh_getsock()
                  implementation */
-
-  result = ssh_statemach_act(conn, &block);
-  *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
+  do {
+    result = ssh_statemach_act(conn, &block);
+    *done = (sshc->state == SSH_STOP) ? TRUE : FALSE;
+    /* if there's no error, it isn't done and it didn't EWOULDBLOCK, then
+       try again */
+  } while(!result && !*done && !block);
   ssh_block2waitfor(conn, block);
 
   return result;