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
>

Reply via email to