possible bug + possible patch

Sergei Vasilyev sergei at numeri.net
Tue Apr 26 17:13:41 GMT 2005


OS: FreeBSD 5.2.1
Software: libsmbclient 3.0.13
Situation: sometimes program with this library says to stdout:
"read_socket_data: recv failure for 1032. Error = Resource temporarily unavailable"
(digits may vary).





Source code (fragments):

void auth_fn (const char *server, const char *share, char *_workgroup, int wgmaxlen, char *_username
, int unmaxlen, char *_password, int pwmaxlen)
{
        strncpy(_workgroup, workgroup.c_str(), wgmaxlen-1);
        strncpy(_username ,  username.c_str(), unmaxlen-1);
        strncpy(_password ,  password.c_str(), pwmaxlen-1);
}
...............
ctx = smbc_new_context();
if (!ctx)
{throw e_samba("Can not allocate context for smbclient.");}
ctx->debug = 10;
ctx->timeout = timeout;
ctx->netbios_name = strdup(selfname.c_str());
ctx->workgroup = strdup(workgroup.c_str());
ctx->callbacks.auth_fn = auth_fn;
if (!smbc_init_context(ctx))
{
smbc_free_context(ctx, false); ctx = NULL;
throw e_samba("Can not initialize smbclient.", strerror(errno));
}
ctx->timeout = timeout;
...................
SMBCFILE * dir = ctx->opendir(ctx, openpathstr.c_str());
if (!dir)
{
   cerr << "    " << "Could not open [" << openpathstr << "] (" << setw(0) << dec << errno << "):" << strerror(errno) << endl;
} else {
.................




It said on stdout (debug level 10):

Connecting to 10.10.1.148 at port 139
socket option SO_KEEPALIVE = 0
socket option SO_REUSEADDR = 0
socket option SO_BROADCAST = 0
socket option TCP_NODELAY = 4
socket option IPTOS_LOWDELAY = 0
socket option IPTOS_THROUGHPUT = 0
socket option SO_REUSEPORT = 0
socket option SO_SNDBUF = 33120
socket option SO_RCVBUF = 66240
socket option SO_SNDLOWAT = 2048
socket option SO_RCVLOWAT = 1
socket option SO_SNDTIMEO = 0
socket option SO_RCVTIMEO = 0
..................................................
 session setup ok
...............................................
[000] 00 44 20 16 00 00 02 06  00 04 01 00 00 00 00 5C  .D ..... .......\
[010] 2A 00                                             *.
write_socket(6,87)
write_socket(6,87) wrote 87
got smb length of 2468
read_socket_data: recv failure for 1032. Error = Resource temporarily unavailable
client_receive_smb failed
size=2468
smb_com=0x32
smb_rcls=0
smb_reh=0
smb_err=0
smb_flg=136
smb_flg2=65
smb_tid=1
smb_pid=22833
smb_uid=0
smb_mid=5
smt_wct=10
smb_vwv[ 0]=   10 (0xA)
smb_vwv[ 1]= 2400 (0x960)
smb_vwv[ 2]=    0 (0x0)
smb_vwv[ 3]=   10 (0xA)
smb_vwv[ 4]=   56 (0x38)
smb_vwv[ 5]=    0 (0x0)
smb_vwv[ 6]= 2400 (0x960)
smb_vwv[ 7]=   68 (0x44)
smb_vwv[ 8]=    0 (0x0)
smb_vwv[ 9]=    0 (0x0)
smb_bcc=2413



Seems that libsmbclient want to receive 2468 bytes, but got only some number
of bytes and there were 1032 bytes it didn't get for some reason. And because of
"Resource temporarily unavailable" is a message for EAGAIN error code, I think that
in some while() cycles when read()'ing or sys_read()'ing from fd when error checking
(in read_data(), read_socket_data(), and in read_socket_with_timeout())
is made by "if (ret == -1)" it should actually be made by "if (ret == -1 && errno != EAGAIN)".
Because EAGAIN is not really an error, but some condition, when program should retry to do
what it want to do.


These are my thoughts about bug I got. Want to listen to your opinion - maybe I'm wrong.
Now I'm upgrading to 3.0.14a and will test this "patch" there to be sure reason is EAGAIN situation.
Patch is apllied (also available at http://numeri.net/storage/smbclient-socketsread.patch ):


===========================================================================
--- source/lib/util_sock.c.orig Wed Apr 27 00:31:12 2005
+++ source/lib/util_sock.c      Wed Apr 27 00:32:46 2005
@@ -264,11 +264,11 @@
                                DEBUG(5,("read_socket_with_timeout: blocking read. EOF from client.\n"));
                                smb_read_error = READ_EOF;
                                return -1;
                        }
                        
-                       if (readret == -1) {
+                       if (readret == -1 && errno != EAGAIN)) {
                                DEBUG(0,("read_socket_with_timeout: read error = %s.\n", strerror(errno) ));
                                smb_read_error = READ_ERROR;
                                return -1;
                        }
                        nread += readret;
@@ -314,11 +314,11 @@
                        DEBUG(5,("read_socket_with_timeout: timeout read. EOF from client.\n"));
                        smb_read_error = READ_EOF;
                        return -1;
                }
                
-               if (readret == -1) {
+               if (readret == -1 && errno != EAGAIN)) {
                        /* the descriptor is probably dead */
                        DEBUG(0,("read_socket_with_timeout: timeout read. read error = %s.\n", strerror(errno) ));
                        smb_read_error = READ_ERROR;
                        return -1;
                }
@@ -348,11 +348,11 @@
                        DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
                        smb_read_error = READ_EOF;
                        return 0;
                }
 
-               if (ret == -1) {
+               if (ret == -1 && errno != EAGAIN) {
                        DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
                        smb_read_error = READ_ERROR;
                        return -1;
                }
                total += ret;
@@ -378,11 +378,11 @@
                        DEBUG(10,("read_socket_data: recv of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) ));
                        smb_read_error = READ_EOF;
                        return 0;
                }
 
-               if (ret == -1) {
+               if (ret == -1 && errno != EAGAIN) {
                        DEBUG(0,("read_socket_data: recv failure for %d. Error = %s\n", (int)(N - total), strerror(errno) ));
                        smb_read_error = READ_ERROR;
                        return -1;
                }
                total += ret;
===========================================================


End of message.



More information about the samba-technical mailing list