Subject: BUG: libssh2_channel_read() does not handle files with size = 0 correctly

BUG: libssh2_channel_read() does not handle files with size = 0 correctly

From: Uli Zappe <uli_at_ritual.org>
Date: Sat, 11 Sep 2010 14:07:09 +0200

Hi,

there's a bug in libssh2_channel_read() that makes it return LIBSSH2_ERROR_EAGAIN instead of 0 when a file of size 0 is to be copied (using the code of the scp_nonblock.c example). As a result, scp times out instead of immediately returning normally after copying a remote file with size 0. (Lock files are a real world example of files with size 0.)

In the limited time I had I could not completely figure out what's happening. If you turn on LIBSSH2_TRACE_SOCKET logging, trying to copy a file of size 0 results in

[libssh2] 0.219610 Socket: Sent 23/23 bytes at 0x26415+0
[libssh2] 0.219643 Socket: Error recving 1 bytes to 0xbfff74af: 35
[libssh2] 0.233947 Socket: Recved 1 bytes to 0xbfff74af
[libssh2] 0.233988 Socket: Recved 1 bytes to 0xbfff74af
[libssh2] 0.233995 Socket: Recved 1 bytes to 0xbfff74af
[libssh2] 0.234002 Socket: Recved 1 bytes to 0xbfff74af
[libssh2] 0.234009 Socket: Recved 1 bytes to 0xbfff74af
[libssh2] 0.234016 Socket: Recved 1 bytes to 0xbfff74af
[libssh2] 0.234023 Socket: Recved 1 bytes to 0xbfff74af
[libssh2] 0.234030 Socket: Recved 1 bytes to 0xbfff74af
[libssh2] 0.234037 Socket: Recved 1 bytes to 0xbfff74af
....

and after some time

[libssh2] 0.234328 Socket: Error recving 16384 bytes to 0x80d520+0: 35
[libssh2] 0.238003 Socket: Recved 784/16384 bytes to 0x80d520+0
[libssh2] 0.245598 Socket: Sent 272/272 bytes at 0x10bfa0
[libssh2] 0.245695 Socket: Error recving 16384 bytes to 0x80d520+0: 35
[libssh2] 0.262529 Socket: Recved 848/16384 bytes to 0x80d520+0
[libssh2] 0.271419 Socket: Sent 16/16 bytes at 0x1073a0
[libssh2] 0.271537 Socket: Sent 52/52 bytes at 0x1072e0
[libssh2] 0.271557 Socket: Error recving 16384 bytes to 0x80d520+0: 35
....

I could trace the issue back to _libssh2_transport_read(), lines 375-394 in transport.c (libssh2-1.2.7). After all the looping from above _libssh2_recv() (which is basically simply recv()) is called from within _libssh2_transport_read() with PACKETBUFSIZE = 16384 and remainbuf = 0 and returns nread = -1 and sets errno to EAGAIN. As a result, transport.c bails out at line 394 and returns LIBSSH2_ERROR_EAGAIN.

This leads back to _libssh2_channel_read(), line 1693 in channel.c, from which _libssh2_transport_read() was called, and makes this function bail out in turn at line 1794, again with LIBSSH2_ERROR_EAGAIN.

This, in turn, finally makes src/scp.c bail out at line 392, with NULL and libssh2 error set to LIBSSH2_ERROR_EAGAIN.

So basically, LIBSSH2_ERROR_EAGAIN is propagated upwards from recv(), but I don't really understand what exactly is going on here. But in any case, libssh2_channel_read() must not return LIBSSH2_ERROR_EAGAIN when a file of size 0 is (successfully!) copied (which of course actually just means that an empty file with the name of the source file is created locally).

            Bye
                    Uli
________________________________________________________

  Uli Zappe, Solmsstraße 5, D-65189 Wiesbaden, Germany
  http://www.ritual.org
  Fon: +49-700-ULIZAPPE
  Fax: +49-700-ZAPPEFAX
________________________________________________________

_______________________________________________
libssh2-devel http://cool.haxx.se/cgi-bin/mailman/listinfo/libssh2-devel
Received on 2010-09-11