Skip to Content.
Sympa Menu

freetds - Re: [freetds] dbsqlexec() never returns

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: "ZIGLIO, Frediano, VF-IT" <Frediano.Ziglio AT vodafone.com>
  • To: "FreeTDS Development Group" <freetds AT lists.ibiblio.org>
  • Subject: Re: [freetds] dbsqlexec() never returns
  • Date: Mon, 4 Jun 2007 10:11:17 +0200

>
> Hi,
>
> We use the FreeTDS C library on a Solaris 10 system to send a
> call to a
> database procedure on a SQL Server database on a Windoze box.
> We were
> using the 0.63 stable release, but were getting an occasional
> (~ once per 2
> months) timeout issue whereby the dbsqlexec() function would never
> return. With the recent improvements to timeout we changed to the
> development release 0.65 from 9th January 2007.
>
> All of our testing worked fine, but when we went live with
> it, we got the
> dbsqlexec() function not returning about once a day. Turning
> on debugging
> showed the problem to be with tds_goodwrite().
>
> I looked at the code, and saw what I thought could be several
> problems. So
> I made a few changes, and added some extra debugging, and
> installed the new
> version. We have not had a problem since (10 days now).
> Unfortunately, I
> am unable to ascertain which of the changes I made resolved
> the actual
> problem that we had, because the problem only occurs
> intermittently on the
> live system, and not on the test system. So I thought I
> would detail the
> changes that were made so that someone else may be able to
> make use of them.
>
> Firstly, the Solaris man page for select(3c) states that if a
> select() call
> times out, then the three fds parameters have their bits
> cleared. In the
> FreeTDS tds_select() function (in net.c), the select() call
> is in a loop
> with a 1 second time out, so if the socket is not available
> for writing
> within the first second, then it will pointlessly wait the
> remaining period
> of the configuration timeout, and then timeout. I fixed this
> by always
> setting poll_seconds to timeout_seconds (line 334), and
> removed the end_ms
> and diff_time code (lines 371 to 380), just leaving "if (ptv) break;".
>

I realized now the problem... tds_select do not set again sockets in
fd_sets...

Fixed with
http://freetds.cvs.sourceforge.net/freetds/freetds/src/tds/net.c?r1=1.61
&r2=1.62&sortby=date
There is not a "hang" test in dblib to catch this problem.

....
>
> *** old/net.c Tue Jan 9 05:18:41 2007 UTC
> --- new/net.c Thu May 21 04:37:49 2007 UTC
> ***************
> *** 321,324 ****
> --- 321,326 ----
> {
> int rc, seconds;
> + // brent 21-May-07 - Always select for full timeout
> + const unsigned int poll_seconds = timeout_seconds;
>
> assert(tds != NULL);
> ***************
> *** 332,341 ****
> */
> seconds = timeout_seconds;
> - const unsigned int poll_seconds = (tds->tds_ctx &&
> tds->tds_ctx->int_handler)? 1 : timeout_seconds;
> assert(seconds >= 0);
> do {
> struct timeval tv, *ptv = timeout_seconds? &tv : NULL;
> - unsigned int end_ms = poll_seconds * 1000 + tds_gettime_ms();
> -
> /*
> * The poll loop. We exit on the first of these events:
> --- 334,340 ----
> ***************
> *** 369,382 ****
>
> if (ptv) {
> - const int diff_time = (int) (end_ms -
> tds_gettime_ms());
> -
> - if (diff_time < 0)
> break;
> -
> - tv.tv_sec = diff_time / 1000;
> - tv.tv_usec = (diff_time % 1000) * 1000;
> -
> - if (tv.tv_sec > poll_seconds || tv.tv_usec > 1000000)
> - break; /* shouldn't happen; start again */
> }
> }
> --- 368,372 ----

these 2 changes should now not be necessary

... applied ...

> ***************
> *** 679,683 ****
> case TDS_INT_TIMEOUT:
> tds_send_cancel(tds);
> ! continue; /* fixme: or return? */
> default:
> case TDS_INT_CANCEL:
> --- 670,675 ----
> case TDS_INT_TIMEOUT:
> tds_send_cancel(tds);
> ! // brent 21-May-07 - Return fail seems more sensible then continue
> ! return 0;
> default:
> case TDS_INT_CANCEL:

I realized now that this patch write side... perhaps it's right... we
send cancel so we should expect server to honor cancel and return some
result, so it's wrong to wait for write again !!
I'm finding a way to reproduce it...

freddy77





Archive powered by MHonArc 2.6.24.

Top of Page