[freetds] db-library : SIGSEGV on dbexit()

GUTIERREZ Pablo TESIS-TAMSA Tesgup at tamsa.com.mx
Tue Jun 10 19:49:35 EDT 2003

OK. I thought dbexit() just called dbclose() one for each open connection.
MS SQL 2000 documentation says this about dbexit():

The dbexit function calls dbclose repeatedly for all open DBPROCESS
structures. The dbclose function cleans up any activity associated with a
DBPROCESS structure and frees the space.

You can use dbclose directly to close just a single DBPROCESS structure."

I understood that calling dbexit() was the same as calling dbclose() (for a
single DBPROC).


-----Original Message-----
From: Lowden, James K [mailto:LowdenJK at bernstein.com] 
Sent: Tuesday, June 10, 2003 4:10 PM
To: 'FreeTDS Development Group'
Subject: RE: [freetds] db-library : SIGSEGV on dbexit()

> From: GUTIERREZ Pablo TESIS-TAMSA [mailto:Tesgup at tamsa.com.mx]
> Sent: June 10, 2003 4:04 PM
> I'm using FREE-TDS 0.61.1, and I'm having a problem with the 
> My code is similar to this one:
> dbinit();
> DBSETUSER (login,...
> ....
> for (;;)
> {
> 	sleep (5);
> 	dbproc=dbopen(login,"anything");			
> 	dbcmd (dbproc, "INSERT INTO ... ");
> 	if (dbsqlexec (dbproc) != SUCCESS)
> 	{
> 		exit (-1);
> 	}
> 	...
> 	...
> 	dbexit();
> }
> The first time the loop runs, it goes fine.
> But the second time, it throws a SIGSEGV signal in the execution of
> dbexit();
> I know I should use dbclose() instead of dbexit() in this 
> case, but, why the exception?

Hmmm.  The real surprise is that you got as far as dbexit() on the second
iteration, that you could use dbopen() after having freed the resources
allocated with dbinit().  

It's best to think of dbinit/dbexit and dbopen/dbclose as malloc/free pairs,
because that's what they call.  The answer to your question is that dbexit()
calls tds_free_context(), which frees the context pointer and does not set
it to NULL.  

We could set it to NULL, of course, and maybe we should, but we'd only mask
the problem; you'd get in to trouble eventually, relying on freed resources.
For example, your snippet doesn't check to see if dbopen() returns NULL
before passing dbproc to dbcmd().  dbcmd()'s behavior is undefined at that
point: we could return FAIL or segfault dereferencing the NULL pointer.
That's a design choice insofar as we adhere to the letter of the
documentation.  (Emulating each vendor's behavior for all error conditions
would be wild goose chase.)  IMHO it's better to die early and noisy when
presented with invalid inputs, because they usually indicate, as in the
instant case, a logic error.  

One of these days, freetds.conf will be parsed and loaded by dbinit(),
instead of dbopen(), as it is now.  When that happens, a call to dbopen()
after dbexit() will certainly fail.  


The information contained in this transmission may contain privileged and
confidential information and is intended only for the use of the person(s)
named above. If you are not the intended recipient, or an employee or agent
responsible for delivering this message to the intended recipient, any
review, dissemination, distribution or duplication of this communication is
strictly prohibited. If you are not the intended recipient, please contact
the sender immediately by reply e-mail and destroy all copies of the
original message. Please note that we do not accept account orders and/or
instructions by e-mail, and therefore will not be responsible for carrying
out such orders and/or instructions.

FreeTDS mailing list
FreeTDS at lists.ibiblio.org

More information about the FreeTDS mailing list