Created
February 6, 2012 23:20
-
-
Save bagder/1755821 to your computer and use it in GitHub Desktop.
sftp_read - patch
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From 0e8573ef1d11b0f0a912223afda6f5802b54f5cd Mon Sep 17 00:00:00 2001 | |
From: Daniel Stenberg <[email protected]> | |
Date: Mon, 6 Feb 2012 23:27:12 +0100 | |
Subject: [PATCH] sftp_read: avoid data *and* EAGAIN | |
Whenever we have data and is about to call a function that *MAY* return | |
EAGAIN we must return the data now and wait to get called again. Our API | |
only allows data *or* EAGAIN and we must never try to get both. | |
--- | |
src/sftp.c | 43 +++++++++++++++++++++++++------------------ | |
1 files changed, 25 insertions(+), 18 deletions(-) | |
diff --git a/src/sftp.c b/src/sftp.c | |
index 48da9f2..dd53355 100644 | |
--- a/src/sftp.c | |
+++ b/src/sftp.c | |
@@ -1085,7 +1085,6 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, | |
struct sftp_pipeline_chunk *chunk; | |
struct sftp_pipeline_chunk *next; | |
ssize_t rc; | |
- size_t eagain = 0; | |
size_t total_read = 0; | |
struct _libssh2_sftp_handle_file_data *filep = | |
&handle->u.file; | |
@@ -1116,6 +1115,8 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, | |
channel_write here to enlarge the receive window */ | |
if(sftp->read_state == libssh2_NB_state_sent) | |
goto send_read_requests; | |
+ else if(sftp->read_state == libssh2_NB_state_sent2) | |
+ goto read_acks; | |
/* We allow a number of bytes being requested at any given time without | |
having been acked - until we reach EOF. */ | |
@@ -1218,16 +1219,17 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, | |
while(chunk) { | |
if(chunk->lefttosend) { | |
+ if(total_read) | |
+ /* since we risk getting EAGAIN below, we return here if there | |
+ is data available */ | |
+ return total_read; | |
+ | |
rc = _libssh2_channel_write(channel, 0, | |
&chunk->packet[chunk->sent], | |
chunk->lefttosend); | |
if(rc < 0) { | |
- if(rc != LIBSSH2_ERROR_EAGAIN) | |
- /* error */ | |
- return rc; | |
- eagain++; | |
sftp->read_state = libssh2_NB_state_sent; | |
- break; | |
+ return rc; | |
} | |
/* remember where to continue sending the next time */ | |
@@ -1243,6 +1245,10 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, | |
chunk = _libssh2_list_next(&chunk->node); | |
} | |
+ read_acks: | |
+ | |
+ sftp->read_state = libssh2_NB_state_idle; | |
+ | |
/* | |
* Count all ACKed packets and act on the contents of them. | |
*/ | |
@@ -1261,15 +1267,17 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, | |
an ACK for it just yet */ | |
break; | |
+ if(total_read) | |
+ /* since we risk getting EAGAIN below, we return here if there | |
+ is data available */ | |
+ return total_read; | |
+ | |
rc = sftp_packet_requirev(sftp, 2, read_responses, | |
chunk->request_id, &data, &data_len); | |
- if (rc == LIBSSH2_ERROR_EAGAIN) { | |
- eagain++; | |
- break; | |
+ if (rc < 0) { | |
+ sftp->read_state = libssh2_NB_state_sent2; | |
+ return rc; | |
} | |
- else if (rc) | |
- return _libssh2_error(session, rc, | |
- "Error waiting for FXP_READ ACK"); | |
/* | |
* We get DATA or STATUS back. STATUS can be error, or it is FX_EOF | |
@@ -1353,12 +1361,11 @@ static ssize_t sftp_read(LIBSSH2_SFTP_HANDLE * handle, char *buffer, | |
chunk = next; | |
} | |
- if(total_read) | |
- return total_read; | |
- else if(eagain) | |
- return _libssh2_error(session, LIBSSH2_ERROR_EAGAIN, | |
- "Would block sftp_read"); | |
- return 0; | |
+ if(! total_read) { | |
+ fprintf(stderr, "MOO\n"); | |
+ } | |
+ | |
+ return total_read; | |
} | |
/* libssh2_sftp_read | |
-- | |
1.7.9 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment