Ticket #94 (closed defect)

Opened 8 years ago

Last modified 8 years ago

channel_read returns LIBSSH2_ERROR_EAGAIN, no data on socket

Reported by: anonymous Owned by: bagder
Priority: normal Milestone:
Component: API Version:
Keywords: Cc: bagder
Blocked By: Blocks:

Description

While using libssh2_channel_read_ex(), I found that when the last of the data has been read, the libssh2_channel_read_ex() may return LIBSSH2_ERROR_EAGAIN, but a poll() on the socket times out (eventually). I diagnosed this as packets (channel eof and channel close) in memory, but not processed, so libssh2_channel_eof() remains false. Root caused as a "single shot" call to _libssh2_transport_read() in channel_read(). No call to _libssh2_transport_read() should be made unless the caller continues to call the function until it returns a non-positive value (0 or negative). This will prevent it from leaving unprocessed buffers in memory.

Change History

comment:1 Changed 8 years ago by bagder

This explanation is not clear to me. If the reason for the LIBSSH2_ERROR_EAGAIN is a "single shot" call to _libssh2_transport_read() in channel_read() then didn't that transport function return EAGAIN? If so, what good would adding a loop do?

Or perhaps put in another way: can you please provide a patch showing what you suggest?

comment:2 Changed 8 years ago by anonymous

The transport function did not return EAGAIN. It processed a full packet (fullpacket()), and returned the result (the packet type). Because _libssh2_transport_read() returns after processing just one packet, additional packets may be waiting (in memory) to be processed by future calls to _libssh2_transport_read(). To resolve this I changed channel_read() in channel.c (around line 1777):

Was:

rc = _libssh2_transport_read(session);

Now:

rc = 1;

while (rc > 0)

rc = _libssh2_transport_read(session);

comment:3 Changed 8 years ago by bagder

Ok, now I understand you perfectly and I also see that you're entirely correct. This actually means we can simplify the channel_read() function since we can do the transport_read() loop the same way independent of the state at the top of the function.

See the commit I just did. Please verify this and tell me if it fixes your problem!

Thanks a lot. If you tell me your real name, I'll give you proper credit in the changelog etc.

Note: See TracTickets for help on using tickets.