On Tue, 13 Sep 2011, Daniel Stenberg wrote:

Quite right. I'll follow up with a fix that keeps the state better to avoid this. Although it seems to be a rather rare case in my tests...

See attachment.

But really, we need to put a more generic concept in place - as Henrik mentioned before - to prevent that this kind of errors sneak in all over.

I'm gonna give this some further thoughts and come back with some kind of suggestion.

I think my sftp_read and window adjust patches probably can go in anyway, as they should at least make the situation better.

--

 / daniel.haxx.se
From 30e28817f2b7d834447ab5cb1ec920c11181a52d Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <dan...@haxx.se>
Date: Tue, 13 Sep 2011 20:16:59 +0200
Subject: [PATCH] sftp_read: use a state variable to avoid bad writes

When a channel_write call has gotten an EAGAIN back, we try harder to
continue the same write in the subsequent invoke.
---
 src/sftp.c |   11 +++++++++++
 src/sftp.h |    5 +----
 2 files changed, 12 insertions(+), 4 deletions(-)

diff --git a/src/sftp.c b/src/sftp.c
index 45e0439..357b87b 100644
--- a/src/sftp.c
+++ b/src/sftp.c
@@ -1107,6 +1107,12 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
         filep->data = NULL;
     }
 
+    /* if we previously aborted a channel_write due to EAGAIN, we must
+       continue that writing so that we don't risk trying to send another
+       channel_write here to enlarge the receive window */
+    if(sftp->read_state == libssh2_NB_state_sent)
+        goto send_read_requests;
+
     /* We allow a number of bytes being requested at any given time without
        having been acked - until we reach EOF. */
     if(!filep->eof) {
@@ -1198,6 +1204,8 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
                           to create more packets */
     }
 
+  send_read_requests:
+
     /* move through the READ packets that haven't been sent and send as many
        as possible - remember that we don't block */
     chunk = _libssh2_list_first(&handle->packet_list);
@@ -1207,11 +1215,14 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer,
             rc = _libssh2_channel_write(channel, 0,
                                         &chunk->packet[chunk->sent],
                                         chunk->lefttosend);
+            sftp->read_state = libssh2_NB_state_idle;
             if(rc < 0) {
                 if(rc != LIBSSH2_ERROR_EAGAIN)
                     /* error */
                     return rc;
                 eagain++;
+                fprintf(stderr, "bing\n");
+                sftp->read_state = libssh2_NB_state_sent;
                 break;
             }
 
diff --git a/src/sftp.h b/src/sftp.h
index 99636fa..44edc36 100644
--- a/src/sftp.h
+++ b/src/sftp.h
@@ -1,7 +1,7 @@
 #ifndef _LIBSSH2_SFP_H
 #define _LIBSSH2_SFTP_H
 /*
- * Copyright (C) 2010 by Daniel Stenberg
+ * Copyright (C) 2010, 2011 by Daniel Stenberg
  * Author: Daniel Stenberg <dan...@haxx.se>
  *
  * Redistribution and use in source and binary forms,
@@ -160,9 +160,6 @@ struct _LIBSSH2_SFTP
 
     /* State variables used in libssh2_sftp_read() */
     libssh2_nonblocking_states read_state;
-    unsigned char *read_packet;
-    uint32_t read_request_id;
-    size_t read_total_read;
 
     /* State variables used in libssh2_sftp_readdir() */
     libssh2_nonblocking_states readdir_state;
-- 
1.7.5.4

_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel

Reply via email to