问题
After 2 days battling, I try asking help here. I'm using unixODBC (2.2.11) to work with DB2 (iSeries) and PHP (5.3) on a CentOS 5.4 server. I guess it's since the upgrade of PHP from 5.1 to 5.3, I get PHP to segfault on certain queries. After some investigation, I discovered the problem appears on some queries with long char fields, for example with this table :
TABLE (
CONTRACTID NUMERIC,
SOMETEXT CHAR(583)
)
This simple piece of code provokes the segfault :
try {
$conn = new PDO("odbc:".$dsn, $username, $password, array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION)
);
}
catch (Exception $e) {
echo $e->getMessage();
}
$sql = 'SELECT * FROM LIB.TABLE ';
$stmt = $conn->prepare($sql);
$vals = $stmt->execute();
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
Is there any column length limit or a bug with unixODBC and/or PHP >= 5.1 ? This web application worked quite great, then I got into this problem..
Btw, I tested with a more up-to-date 64bits CentOS 6.2 machine with unixODBC 2.2.14 and PHP 5.3, and the problem is the same.
Any help greatly appreciated,
Thanks
fabien
UPDATE : Using the PHP odbc functions, it works :
$conn = odbc_connect($dsn, $username, $password);
$res = odbc_exec($conn, $sql);
$rows = odbc_fetch_array($res);
So the problem is more tied to PDO, any idea?
回答1:
Ran into the same problem here. Found that the 64-bit php-odbc module is causing the seg fault when returning a field with a NULL value. A workaround is to coalesce each field in which a NULL value could exist. It's not a good solution. I'm looking at the php-odbc.c code, but I can't guarantee a fix.
Workaround: SELECT COALESCE(CHAR(fieldname),'') FROM ...
I think I'm going to replace this server with a 32-bit version. I have others that work just fine.
回答2:
I had a similar problem on Centos 6.3 with Vertica 6 and the UnixODBC that comes with Centos, PHP would just segfault. So I ran strace php mytest.php
and found that it tried to find and open /usr/lib64/libodbccr.so.1
However Centos 6.3 only has libodbccr.so.2
So the quick and dirty fix is to do the following in: /usr/lib64
ln -s libodbccr.so.2 libodbccr.so.1
Use at your own risk!
回答3:
I cannot say I know of any issues in pdo (which I don't use anyway) or unixODBC or the DB2 driver. I'm not sure from your email if your first platform is using 64 bit builds or 32 bit builds but ODBC changed when Microsoft added 64 bit support (see SQLLEN/SQLULEN and 32/64 bit platforms and 64-bit ODBC). Basically, some ODBC APIs had a type changed from SQLINTEGER to SQLLEN and an SQLLEN is 64bits in a 64 bit build and 32 bits in a 32 bit build. However, as no one was to know Microsoft was going to do this and some of these arguments were actually described in the spec as 32 bit quantities some ODBC driver writers had already built ODBC drivers for 64 bit platforms using 32 bit quantities for these arguments. Obviously, if you mix an application or driver manager built one way with a driver built the other way all hell can break lose and you very well may get segfaults. So, firstly, if you are using 64 bit binaries you need to check your ODBC driver was built correctly - speak to IBM.
unixODBC 2.2.11 is rather old now and I know issues have been fixed but I'm still using it extensively and only have one small issue in the cursor library. Anyway, you tried 2.2.14 and the problem was the same. I doubt it is an unixODBC issue but that is only based on my extensive experience with it and not because I know for a fact.
Now, assuming you don't fall into the situation outlined above you can do a number of things. Try enabling logging in unixODBC then you can see what ODBC calls are being made and which one fails. You might also get a clue from the arguments passed as to what might be going on. You enable logging by adding the following to your odbcinst.ini file:
[ODBC]
Trace=yes
TraceFile=/tmp/unixodbc.log
Look for a call to SQLBindCol or SQLGetData for the column in question. If this does not get you anywhere you can try pasting the end of it here and I'll look at it.
If you can run your PHP program from the command line and you install gdb you can run it under gdb and it will show you a stack dump of where the problem occurred. Just do gdb /path/to/php then type r myscript.php and enter to run it and when it segfaults you can use the bt (backtrace) command to show the stack. That should identify which code is causing the segfault although it is not necessarily that code which is fault (e.g., if php passed a pointer to a buffer of 10 bytes but lies and says it is 100 bytes the code which writes off the end is not at fault).
来源:https://stackoverflow.com/questions/10927983/segfault-with-unixodbc-db2-php-centos