Skip to Content.
Sympa Menu

freetds - [freetds] stuck in endless loop in tds_goodread

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: Largo <largowww AT gmail.com>
  • To: freetds AT lists.ibiblio.org
  • Subject: [freetds] stuck in endless loop in tds_goodread
  • Date: Thu, 1 Feb 2007 10:50:20 +0100

Hi,

I had a problem posted here 2 weeks ago:
https://lists.ibiblio.org/sympa/arc/freetds/2007q1/021045.html which still
isn't solved. But meanwhile I have some more information as I've been
digging in the code of freetds. It seems freetds is stuck in an endless loop
in the function tds_goodread in the file net.c

Here's the function:
static int
tds_goodread(TDSSOCKET * tds, unsigned char *buf, int buflen, unsigned char
unfinished)
{
time_t start, global_start;
int timeout = 0;
int got = 0;
fd_set rfds;
struct timeval tv;

tv.tv_usec = 0;

if (buf == NULL || buflen < 1 || tds == NULL)
return 0;

global_start = start = tds->query_start_time ? tds->query_start_time
: time(NULL);

while (buflen > 0) {
int len;
time_t now = time(NULL);

if (IS_TDSDEAD(tds))
return -1;

FD_ZERO(&rfds);
FD_SET(tds->s, &rfds);

timeout = 0;
if (tds->query_timeout > 0) {
timeout = tds->query_timeout - (now - start);
if (timeout < 1)
timeout = 1;
}
tv.tv_sec = timeout;
if ((len = select(tds->s + 1, &rfds, NULL, NULL, timeout > 0
? &tv : NULL)) > 0) {
len = 0;
if (FD_ISSET(tds->s, &rfds)) {
#ifndef MSG_NOSIGNAL
len = READSOCKET(tds->s, buf + got, buflen);
#else
len = recv(tds->s, buf + got, buflen,
MSG_NOSIGNAL);
#endif
/* detect connection close */
if (len == 0) {
tds_close_socket(tds);
return -1;
}
}
}

if (len < 0) {
switch(sock_errno) {
case TDSSOCK_EINTR:
tdsdump_log(TDS_DBG_NETWORK, "socket read
interrupted\n");
case EAGAIN:
case TDSSOCK_EINPROGRESS:
break;
default:
return -1;
}
len = 0;
}

buflen -= len;
got += len;

now = time(NULL);
if (tds->query_timeout > 0 && now - start >=
tds->query_timeout) {

int timeout_action = TDS_INT_CONTINUE;

tdsdump_log(TDS_DBG_NETWORK, "exceeded query
timeout: %d\n", tds->query_timeout);

if (tds->query_timeout_func && tds->query_timeout)
timeout_action = (*tds->query_timeout_func)
(tds->query_timeout_param, now - global_start)
;

switch (timeout_action) {
case TDS_INT_EXIT:
exit(EXIT_FAILURE);
break;
case TDS_INT_CANCEL:
tds_send_cancel(tds);
break;

case TDS_INT_CONTINUE:
start = now;
default:
break;
}
}

if (unfinished && got)
return got;
}
return got;
}

When my program is running for a while, following is happening: select
returns len=0. This means buflen is never decremented so it stays forever in
the whileloop. If I understand the function correctly, then the timeout
should guard this, but as far as I can see, this can never result in leaving
the while loop. In my case tds->query_timeout_func equals NULL, so
timeout_action is always TDS_INT_CONTINUE.




Archive powered by MHonArc 2.6.24.

Top of Page