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