On Tue, 6 Sep 2011, liuzl wrote:

When sending a internal packet(eg:window adjust packet),
even we may blocked in the last call, try to send it normally

Isn't the bug in the channel_read function "only" that the adjust window functionality breaks when transport_recv() is called until EGAIN in subsequent calls?

I suggest the attached patch instead of yours. It makes sure that the window_adjust function is called again immediately if it was that function that caused the previous EAGAIN return code.

--

 / daniel.haxx.se
From 81bdcf61f38f4a3e532c17d915b2b32a27bee52b Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <dan...@haxx.se>
Date: Thu, 8 Sep 2011 14:25:25 +0200
Subject: [PATCH] _libssh2_channel_read: fix non-blocking window adjusting

If EAGAIN is returned when adjusting the receive window, we must not
read from the transport directly until we've finished the adjusting.
---
 src/channel.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/src/channel.c b/src/channel.c
index be6a680..75b47a5 100644
--- a/src/channel.c
+++ b/src/channel.c
@@ -1754,6 +1754,16 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
                        stream_id);
         channel->read_state = libssh2_NB_state_created;
     }
+
+    /*
+     * =============================== NOTE ===============================
+     * I know this is very ugly and not a really good use of "goto", but
+     * this case statement would be even uglier to do it any other way
+     */
+    if (channel->read_state == libssh2_NB_state_jump1) {
+        goto channel_read_window_adjust;
+    }
+
     rc = 1; /* set to >0 to let the while loop start */
 
     /* Process all pending incoming packets in all states in order to "even
@@ -1765,15 +1775,6 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
     if ((rc < 0) && (rc != LIBSSH2_ERROR_EAGAIN))
         return _libssh2_error(session, rc, "transport read");
 
-    /*
-     * =============================== NOTE ===============================
-     * I know this is very ugly and not a really good use of "goto", but
-     * this case statement would be even uglier to do it any other way
-     */
-    if (channel->read_state == libssh2_NB_state_jump1) {
-        goto channel_read_ex_point1;
-    }
-
     read_packet = _libssh2_list_first(&session->packets);
     while (read_packet && (bytes_read < (int) buflen)) {
         /* previously this loop condition also checked for
@@ -1874,7 +1875,7 @@ ssize_t _libssh2_channel_read(LIBSSH2_CHANNEL *channel, int stream_id,
     if(channel->remote.window_size < (LIBSSH2_CHANNEL_WINDOW_DEFAULT*30)) {
         /* the window is getting too narrow, expand it! */
 
-      channel_read_ex_point1:
+      channel_read_window_adjust:
         channel->read_state = libssh2_NB_state_jump1;
         /* the actual window adjusting may not finish so we need to deal with
            this special state here */
-- 
1.7.5.4

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

Reply via email to