Skip to Content.
Sympa Menu

freetds - [freetds] FreeTDS, C++, and Exceptions

freetds AT lists.ibiblio.org

Subject: FreeTDS Development Group

List archive

Chronological Thread  
  • From: Lenon Kitchens <lenonk AT sanctuary.org>
  • To: freetds AT lists.ibiblio.org
  • Subject: [freetds] FreeTDS, C++, and Exceptions
  • Date: Sat, 17 Jun 2006 03:55:37 -0400

Hi folks,

I have a problem with FreeTDS that I was hoping someone could help me solve. I'm a developer for a company that deals in network management software. Since basically all of our applications need to have the ability to talk to one or more of SQLServer, Oracle, SQLite, Sybase, I have written a C++ library to provide a common interface to all of these APIs.

It wasn't until recently that I noticed a problem with the FreeTDS part of my implementation. I have installed error and message handlers using dberrhandle() and dbmsghandle(). At the end of each of these functions, I throw an exception like so:

throw DBLibException(EGENERAL_EXCEPTION, err.str());

The "err" string is obviously filled out during the function. The problem is that for some reason, this exception goes completely uncaught and results in terminate() being called.

Here's the output of a test program:

[lenon@atllnxdev01 libcentivia]$ ./test
checking tdsport
terminate called after throwing an instance of 'DBLibException'
Aborted

Here's the test program itself:

#include <stdio.h>

int main(void) {
DBConnection *SQLServerConn;
try {
SQLServerConn = DBConnection::buildConnection(SQLServer, "10.0.0.0",
"username", "password");
SQLServerConn->connect("database");

// Foo is obviously an invalid table name which will cause an exception
// to be thrown.
SQLServerConn->execute("select * from foo");
}
catch (DBLibException &e) {
cout << "DBLib Exception: " << e.getErrInfo() << endl;
return -1;
}
}


If I throw this exact same exception immediately before the call to dbsqlexec(), it works fine.

Here are the two installed handlers:

int
sybErrHandler(DBPROCESS *dbProc, int severity, int dbErr, int osErr,
char *dbErrStr, char *osErrStr) {
string err;
// It's OK to end up here in response to a dbconvert() that
// resulted in overflow, so don't exit in that case.
if (dbErr == SYBEICONVI)
return 0;

/*
* For server messages, cancel the query and rely on the
* message handler to spew the appropriate error messages out.
*/
if (dbErr == SYBESMSG)
return INT_CANCEL;

err = "\nDBLIB ERROR: [" + string(dbErrStr) + "]";

if (osErr != DBNOERR)
err += "\nOS ERROR: [" + string(osErrStr) + "]";

throw DBLibException(EGENERAL_EXCEPTION, err);
}

int
sybMsgHandler(DBPROCESS *dbProc, DBINT msgNo, int msgState,
int severity, char *msgText, char *srvName, char *procName, int line) {

if (msgNo == 5701 || msgNo == 5703 || msgNo == 5704)
return (INT_CONTINUE);

stringstream err;
err << "\nDBLIB MESSAGE: [msgno: " << msgNo <<
", level: " << severity << ", State: " << msgState << "]";
if (*srvName)
err << "\nSERVER: [" << srvName << "]";
if (*procName)
err << "\nPROCEDURE: [" << procName << "]";
if (line > 0)
err << "\nLINE: [" << line << "]";

err << "\nMESSAGE: " << msgText;

throw DBLibException(EGENERAL_EXCEPTION, err.str());
}


Any help will be greatly appreciated.

Thanks!

Lenon Kitchens




Archive powered by MHonArc 2.6.24.

Top of Page