The resolution of this issue was to rebuild DBD::ODBC, using an available odbc_config, which correctly informed the build that it should use 64-bit, instead of its defaulting to 32-bit. That cleared up all of these segfault issues.
On May 17, 2:06 pm, martin.ev...@easysoft.com ("Martin J. Evans") wrote: > On 17/05/2011 14:54, eric.b...@barclayscapital.com wrote:> Just a quick > update: > > > We switched back to using the FreeTDS driver under DBD::ODBC with the > > unixODBC ODBC manager on Linux and the segfault problem went away. > > > That seems to suggest to me that it's a problem with the Easysoft driver, > > and I've communicated this to the Easysoft team. > > > BTW, the Easysoft guys have been really terrific; responsive and > > knowledgeable. A real pleasure to work with. Hopefully they can track > > down this bug. > > > Eric > > Eric, I believe Easysoft support are sorting you out but as the problem > I believe you've hit potentially affects anyone else using an older > unixODBC on 64 bit platforms (or one without odbc_config) it is worth > mentioning it here. > > Some background: > > As many of you may know MS invented ODBC and then I believe handed it > over to X/Open. However, since then they have continued making changes > to the API. Before Windows 64 bit operating systems many ODBC APIs were > documented as taking or returning 32 bits values (and I mean that, not > int or long but documented as a 32 bit value which is strange for a C > API). When Windows 64 came along some APIs were changed to take an > SQLLEN/SQLULEN or a pointer to a SQLLEN/SQLULEN and an SQLLEN/SQLULEN > was defined as 32 bits on 32 bit operating systems and 64 bits on 64 bit > operating systems. > > unixODBC and many ODBC drivers who were ahead of MS and building drivers > and driver managers for 64bit platforms could not know what MS were > going to do and they did not all make the same choice. Most stuck with > the API as it was which said 32 bit values. When MS changed ODBC to > introduce SQLLEN/SQLULEN it left some driver writers with a problem and > some had to produce 2 versions of their 64bit drivers - one using 32bit > values for some ODBC API parameters and one using 64bit values as there > were apps out there doing both. > > These days unixODBC supports SQLLEN/SQLULEN and most drivers do and > unixODBC builds out the box with a 64bit SQLLEN/SQLULEN value. However, > this is ascertained at configure time and the header files which go with > unixODBC define SQLLEN/SQLULEN as 32bit or 64bit depending on whether > SIZEOF_LONG_INT is 32 or 64. DBD::ODBC looks for unixODBC's odbc_config > program which can be used to return the cc flags used to build unixODBC > and one of those flags is -DSIZEOF_LONG_INT=64. When DBD::ODBC finds > odbc_config it can add the right flags to the compiler when building > DBD::ODBC. When DBD::ODBC cannot find odbc_config (and it goes out of > its way to find it) it cannot know what to add to the compile line so > adds nothing. The result is that if you build DBD::ODBC on a 64bit > platform against unixODBC and odbc_config is not found SQLLEN/SQLULEN > will be 32 bits in size (incorrectly most of the time) and then APIs > like SQLRowCount which is passed a pointer to a SQLLEN will pass a > pointer to 4 bytes of space instead of 8 - thus corrupting the stack. > > Now, whether your app (or DBD::ODBC or Perl) will segfault or when it > will segfault is just pot luck. It is not a driver bug but a bug in the > building of DBD::ODBC in a way incompatible with unixODBC. > > As a side note to anyone looking after packages for Linux especially > like Ubuntu, Debian etc. Please, please upgrade unixODBC in your package > system to a newer version AND include odbc_config. > > I am sorry this has caused you some problems. I will try and change > DBD::ODBC to issue a warning on 64 bit platforms if odbc_config is not > found but as few people pay much attention to the warnings I'm not sure > what good it will do. > > Martin > > >> -----Original Message----- > >> From: Berg, Eric: IT (NYK) > >> Sent: Friday, May 13, 2011 9:24 AM > >> To: 'Martin J. Evans' > >> Cc: dbi-us...@perl.org > >> Subject: RE: DBD::ODBC Segfaults on SET TEXTSIZE and TRUNCATE TABLE > > >> Thanks, Martin. I've been working with Richard on this for a few days and > >> he's been very helpful. Just not sure what's up here yet, but it was > >> recommended that I upgrade from the 1.3 version that we've got packaged > >> for use here at the bank to 1.4. We'll see if that makes a difference. > > >> Many of the tests of DBD::ODBC are failing as well. I'm looking at that, > >> will upgrade and report my progress back to the list. > > >> Thanks again. > > >>> -----Original Message----- > >>> From: Martin J. Evans [mailto:martin.ev...@easysoft.com] > >>> Sent: Friday, May 13, 2011 3:46 AM > >>> To: Berg, Eric: IT (NYK) > >>> Cc: dbi-us...@perl.org > >>> Subject: Re: DBD::ODBC Segfaults on SET TEXTSIZE and TRUNCATE TABLE > > >>> On 12/05/11 21:39, eric.b...@barclayscapital.com wrote: > >>>> Posted this in the Google Group, but not sure if it's going through, > >> so > >>> I apologize for the duplicate if that's the case. > >>>> We're continuing with our struggles to get Perl working properly to > >>> connect to MS SQL server, and have come up against a nasty bug that > >>> results in segmentation faults when attempting to do a $dbh->do(...) to > >>> set TEXTSIZE or truncate tables. > >>>> I'm running the following: > >>>> Perl : 5.012003 (x86_64-linux) > >>>> OS : linux (2.6.18-194.el5) > >>>> DBI : 1.616 > >>>> DBD::ODBC : 1.29 > >>>> EasySoft ODBC driver: 1.3 > > >>>> MS SQL Server 2008. > > >>>> The following code generates a segfault when _ExecDirect is called at > >>> DBD/ODBC.pm at line 396. > >>>> my $dbh = DBI->connect("dbi:ODBC:MSSQL", $user, $password) || die > >> "Error > >>> connecting: $!"; > >>>> $dbh->{LongReadLen} = 25000; > >>>> $sql = 'SELECT @@TEXTSIZE'; > >>>> $sth = $dbh->prepare($sql); > >>>> $sth->execute(); > > >>>> print "SQL1: $sql:\n"; > >>>> while ( @row = $sth->fetchrow_array ) { > >>>> print join( ", ", @row ), "\n"; > >>>> } > > >>>> $sql = 'set textsize 100'; > >>>> print "SQL2: $sql:\n"; > >>>> $sth = $dbh->do($sql); > >>>> warn 0; > > >>>> And the output is: > > >>>> $ ./set_text_size_test.pl > >>>> SQL1: SELECT @@TEXTSIZE: > >>>> -1 > >>>> SQL2: set textsize 100: > >>>> Segmentation fault (core dumped) > > >>>> and the "0" is never printed. > > >>>> Running this in the Perl debugger shows me that it dies at DBD::ODBC > >> at > >>> line 396, at which point it calls is an XS method defined in ODBC.c on > >>> line 133: > >>>> void > >>>> _ExecDirect( dbh, stmt ) > >>>> SV * dbh > >>>> SV * stmt > >>>> CODE: > >>>> { > >>>> STRLEN lna; > >>>> /*char *pstmt = SvOK(stmt) ? SvPV(stmt,lna) : "";*/ > >>>> ST(0) = sv_2mortal(newSViv( (IV)dbd_db_execdirect( dbh, stmt ) ) > >> ); > >>>> } > > >>>> Anyone have any idea what might be going on here? > > >>>> Also, notice that the initial "SELECT @@TEXTSIZE" returns -1, which is > >>> an unusual value. > >>>> Thanks for any help you might be able to provide. > > >>>> Eric > >>> Eric, > > >>> It does not segfault for me with DBD::ODBC 1.30_1 and our 1.4.18 driver. > >>> I've passed your email onto Easysoft support and they should contact you > >>> soon. > > >>> Martin > >>> -- > >>> Martin J. Evans > >>> Easysoft Limited > >>>http://www.easysoft.com >