OS: FreeBSD 5.2.1 Software: libsmbclient 3.0.14a 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 (source/lib/ util_sock.c) 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. And later when buffer pointer increases it shoudl check if returned value (number of bytes read) was not -1.
Created attachment 1177 [details] patch to fix this problem This patch solves the problem with "Resource temporary unavailable" message described above. But it is not as good as it have to be. First, it will rotate in infinite while() trying to read data from socket, and make processor work hardly. Really there should be select(2) call before read()'ing from socket - this is work for samba developers. Second, I know it have fixed my current problem with EAGAIN error, but I dont know if it makes new problem to libsmbclient or other samba components. This should be tested carefully before releasing patched version. Patch is alose available at http://numeri.net/storage/smbclient-socketsread.patch for downloading if you need it :)
djl implementation concept: 1. check to see if libsmbclient is entering non-blocking mode (and not exiting it) for some reason 2. if that's not it, then check for EAGAIN in receive_smb_raw() and if so, then read remainder of packet with read_socket_with_timeout().
Fixed by checkin r7039
sorry for the same, cleaning up the database to prevent unecessary reopens of bugs.