[freetds] 0.82 RC4 assert(0) on failed to connect

James K. Lowden jklowden at freetds.org
Mon Apr 21 10:43:06 EDT 2008

>     #4  0xb7241085 in retname (retcode=0) at util.c:292
>     #5  0xb72411b4 in tdserror (tds_ctx=0x80f9e78, tds=0x80856b8,
>     #msgno=20009, 
>         errnum=115) at util.c:368
>     #6  0xb725c724 in tds_open_socket (tds=0x80856b8, 
>         ip_addr=0x8085b78 "", port=1433, timeout=90000) at
>         net.c:309
>     #7  0xb7241def in tds_connect (tds=0x80856b8, connection=0x8085a58)
>         at login.c:428
>     #8  0xb7234b16 in DbOpen (handle=0x807f738) at nsfreetds.c:270
>     #9  0xb7270b99 in NsDbOpen () from ./lib/libnsdb.so
>     ...
> It appears that "rc" in tdserror is set from the return of the message
> handler?  Indeed, my custom handler messages both return "0" -- ack.
> I've changed the error message handler to return TDS_INT_CANCEL.

[For anyone tuning in late, this thread applies to AOLserver, which uses
libtds directly.  Normal applications (let's call them) use one of the
three client libraries, all of which prevent the assert error in the

Hi Dossy, 

Yes.  One big change in 0.82 will be that libtds calls back to the client
library's error handler to decide whether to retry or abort.  The callback
function's return value tells libtds what to do.  You no doubt saw the
comment in tdserror():

 	 * Call client library handler.
	 * The client library must return a valid code.  
	 * It is not checked again here.

Cf. src/dblib/dblib.c::dbperror and the comments above

Of course the callback function is written by the user and might not
return one of the specified values (as in your case!).  The client
library's "handler handler" (if you will) is responsible for dealing with
that.  In db-lib, any out-of-range return code is converted to INT_EXIT.  

This is actually a specific instance of the general purpose of each
library's "handler handler".  Each library defines its own way to deal
with timeouts, and libtds doesn't care which client library happens to be
in use; it has its own callback specification.  It's the job of the
"handler handler" to wrap the caller's handler (if any) and provide
conforming behavior for libtds.  

Hope that's clear!  

> Yes, I realize that direct use of libtds isn't supported, but this
> caught me by surprise.

I'm sure.  Over the last year or two I've worked to rationalize error
handling. The philosophy is that most error detection and handling should
be done by the client library, and libtds can expect to be called
correctly.  Life is simpler that way.  

For the sake of a framework, let's say errors are of two kinds: logical
and runtime.  Runtime errors -- server not available, library misuse --
cannot be handled at compile time.  They provoke error messages that
inform the user what went wrong.  Logical errors are bugs embedded in the
code that can be prevented by testing, etc.  They are handled more simply:
with a log message (maybe) and an assertion.  (I'm excluding server
messages -- bad SQL, etc. -- because they're not errors insofar as the
library is concerned.  They're just data.) 

The client library handles almost all runtime errors and must *prevent*
logical errors.  It is the job of the client library not to make invalid
calls upon libtds, no matter what the application or server does.  If it
fails to do so, the results are, as the compiler writers say, undefined. 
For the most part libtds assumes (or, more and more, asserts) inputs from
the client library are valid.  



More information about the FreeTDS mailing list