Skip Menu |

This queue is for tickets about the DBD-DB2 CPAN distribution.

Report information
The Basics
Id: 53525
Status: resolved
Priority: 0/
Queue: DBD-DB2

People
Owner: opendev [...] us.ibm.com
Requestors: dave [...] awk.cz
Cc:
AdminCc:

Bug Information
Severity: Critical
Broken in: 1.76
Fixed in: (no value)



Subject: Segfault from setErrorFromDiagRecInfo
Hello, I found a new bug causing segfaults when the DB2 query returns no rows. Using DBI trace, I can see I'm also getting a "silent" DB2 error during prepare() of my SQL statement. May be this issue is triggered by a combination of these two, I don't know. This is the segfault itself: Program received signal SIGSEGV, Segmentation fault. strlen () at ../sysdeps/i386/i486/strlen.S:69 69 ../sysdeps/i386/i486/strlen.S: No such file or directory. in ../sysdeps/i386/i486/strlen.S Current language: auto The current source language is "auto; currently asm". (gdb) bt #0 strlen () at ../sysdeps/i386/i486/strlen.S:69 #1 0xb7cab776 in set_err_char (h=0x8354918, imp_xxh=0x84397f8, err_c=0xb7c76e47 "", err_i=100, errstr=0x0, state=0xbfffec3e "00000", method=0x0) at DBI.xs:604 #2 0xb7c6c4ea in setErrorFromDiagRecInfo (perlHandle=<value optimized Show quoted text
out>, handleType=<value optimized out>, handle=65537, err=0xb7c76e47 "")
at dbdimp.c:112 #3 0xb7c6c693 in diagnoseError (perlHandle=0x8354918, handleType=9376, handle=65537, rc=100, what=0xb7c76dd8 "Fetch Failed") at dbdimp.c:54 #4 0xb7c72ee7 in db2_st_fetch (sth=0x8354918, imp_sth=0x84397f8) at dbdimp.c:2539 #5 0xb7c67cc7 in XS_DBD__DB2__st_fetchrow_arrayref (my_perl=0x8188008, cv=0x8291950) at DB2.xs:399 #6 0xb7cb9299 in XS_DBI_dispatch (my_perl=0x8188008, cv=0x8326040) at DBI.xs:3292 #7 0x080b12c0 in Perl_pp_entersub () #8 0x080af688 in Perl_runops_standard () #9 0x080adbb2 in perl_run () #10 0x08063ffd in main () And this is what is reported in DBI trace log: DBI::db=HASH(0x8ad1960) trace level set to 0x0/1 (DBI @ 0x0/0) in DBI 1.609-ithread (pid 5042) DB2: 2009-11-20-06.00.00 - 2009-11-21-06.00.00 !! ERROR: '-99999' '[IBM][CLI Driver] CLI0137E Information type out of range. SQLSTATE=HY096' (err#1) <- prepare_cached(' SELECT count(RPT.ACC_BODYHIST.KANR) count FROM RPT.ACC_BODYHIST WHERE RPT.ACC_BODYHIST.STATUS0 = ? AND RPT.ACC_BODYHIST.MDATUMZEIT >= TIMESTAMP( CAST(? AS TIMESTAMP) ) AND RPT.ACC_BODYHIST.MDATUMZEIT < TIMESTAMP( CAST(? AS TIMESTAMP) ) GROUP BY RPT.ACC_BODYHIST.STATUS0; ')= DBI::st=HASH(0x8ad1c90) at count line 145 !! ERROR: '-99999' CLEARED by call to execute method <- execute('Z100', '2009-11-20-06.00.00', ...)= -1 at count line 159 Segmentation fault The weird thing is that the prepare is actually OK and subsequent SELECTs with actual result rows are OK. I only trigger the segfault when there are no rows returned. I couldn't find much about CLI0137E and whatever I do with my statement, it doesn't go away. I have just installed a new DB2 administration client version, but I haven't tried this perl app with previous version. This client is the latest version available in the IBM Software Access Catalog and is much newer than my previous one: DB21085I Instance "dave" uses "32" bits and DB2 code release "SQL08010" with level identifier "01010106". Informational tokens are "DB2 v8.1.0.0", "s021023", "", and FixPak "0". Product is installed at "/opt/IBM/db2/V8.1". DBI is 1.609-1 (Ubuntu) DBD::DB2 is 1.76 (CPAN) Anyway, I found the issue and fixed it. I'm attaching a patch for dbdimp.c. You can see that setErrorFromDiagRecInfo() initializes var "message" with NULL. In an obvious case, this value is not updated and is passed to DBI's set_err_char() as "errstr", which is then duplicated and strlen()'d without any checking. I think DBI should sanitize its parameters, but DBD::DB2 also shouldn't pass NULLs around unnecessarily. :) After initializing message = "", the segfault disappears and my code is working again. I'd be very much interested in what "CLI0137E Information type out of range. SQLSTATE=HY096" means and why the statement works fine despite it. Here's the same DBD::DB2 call sequence, but with the highest DB2_TRACE. You won't get segfault this way, because when DBIc_TRACE_LEVEL >= 3, the switch statement in setErrorFromDiagRecInfo() updates "message" itself: DBI::db=HASH(0x94f9600) trace level set to 0x0/5 (DBI @ 0x0/0) in DBI 1.609-ithread (pid 10458) DB2: 2009-11-20-06.00.00 - 2009-11-21-06.00.00 -> prepare for DBD::DB2::db (DBI::db=HASH(0x94f9690)~0x94f9600 ' SELECT count(RPT.ACC_BODYHIST.KANR) count FROM RPT.ACC_BODYHIST WHERE RPT.ACC_BODYHIST.STATUS0 = ? AND RPT.ACC_BODYHIST.MDATUMZEIT >= TIMESTAMP( CAST(? AS TIMESTAMP) ) AND RPT.ACC_BODYHIST.MDATUMZEIT < TIMESTAMP( CAST(? AS TIMESTAMP) ) GROUP BY RPT.ACC_BODYHIST.STATUS0; ') thr#932d008 New 'DBI::st' (for DBD::DB2::st, parent=DBI::db=HASH(0x94f9600), id=undef) dbih_setup_handle(DBI::st=HASH(0x94f9930)=>DBI::st=HASH(0x94f98d0), DBD::DB2::st, 9477790, Null!) dbih_make_com(DBI::db=HASH(0x94f9600), 93542f8, DBD::DB2::st, 160, 0) thr#932d008 dbih_setup_attrib(DBI::st=HASH(0x94f98d0), Err, DBI::db=HASH(0x94f9600)) SCALAR(0x94776b0) (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), State, DBI::db=HASH(0x94f9600)) SCALAR(0x9477730) (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), Errstr, DBI::db=HASH(0x94f9600)) SCALAR(0x94776f0) (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), TraceLevel, DBI::db=HASH(0x94f9600)) 5 (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), FetchHashKeyName, DBI::db=HASH(0x94f9600)) 'NAME' (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), HandleSetErr, DBI::db=HASH(0x94f9600)) undef (not defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), HandleError, DBI::db=HASH(0x94f9600)) undef (not defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), ReadOnly, DBI::db=HASH(0x94f9600)) undef (not defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), Profile, DBI::db=HASH(0x94f9600)) undef (not defined) dbd_st_prepare'd sql f65537 SELECT count(RPT.ACC_BODYHIST.KANR) count FROM RPT.ACC_BODYHIST WHERE RPT.ACC_BODYHIST.STATUS0 = ? AND RPT.ACC_BODYHIST.MDATUMZEIT >= TIMESTAMP( CAST(? AS TIMESTAMP) ) AND RPT.ACC_BODYHIST.MDATUMZEIT < TIMESTAMP( CAST(? AS TIMESTAMP) ) GROUP BY RPT.ACC_BODYHIST.STATUS0; statement = SELECT count(RPT.ACC_BODYHIST.KANR) count FROM RPT.ACC_BODYHIST WHERE RPT.ACC_BODYHIST.STATUS0 = ? AND RPT.ACC_BODYHIST.MDATUMZEIT >= TIMESTAMP( CAST(? AS TIMESTAMP) ) AND RPT.ACC_BODYHIST.MDATUMZEIT < TIMESTAMP( CAST(? AS TIMESTAMP) ) GROUP BY RPT.ACC_BODYHIST.STATUS0; imp_sth->statement= SELECT count(RPT.ACC_BODYHIST.KANR) count FROM RPT.ACC_BODYHIST WHERE RPT.ACC_BODYHIST.STATUS0 = :p1 AND RPT.ACC_BODYHIST.MDATUMZEIT >= TIMESTAMP( CAST(:p2 AS TIMESTAMP) ) AND RPT.ACC_BODYHIST.MDATUMZEIT < TIMESTAMP( CAST(:p3 AS TIMESTAMP) ) GROUP BY RPT.ACC_BODYHIST.STATUS0; scanned 3 distinct placeholders fbh 0: 'COUNT' , type 4, 11, dsize 10, p0 s154487488 out: ftype 1, indp 0, bufl 45, rlen 45 !! ERROR: '-99999' '[IBM][CLI Driver] CLI0137E Information type out of range. SQLSTATE=HY096' (err#0) <- prepare= DBI::st=HASH(0x94f9930) at ./count line 147 via at ./count line 36 !! ERROR: '-99999' CLEARED by call to execute method -> execute for DBD::DB2::st (DBI::st=HASH(0x94f9930)~0x94f98d0 'Z100' '2009-11-20-06.00.00' '2009-11-21-06.00.00') thr#932d008 bind :p1 <== 'Z100' (attribs: <no attribs>) bind :p1: db2_param_type=1, db2_c_type=1, db2_type=1, PRECISION=0, SCALE=0, Maxlen=0, Described bind :p2 <== '2009-11-20-06.00.00' (attribs: <no attribs>) bind :p2: db2_param_type=1, db2_c_type=1, db2_type=93, PRECISION=0, SCALE=6, Maxlen=0, Described bind :p3 <== '2009-11-21-06.00.00' (attribs: <no attribs>) bind :p3: db2_param_type=1, db2_c_type=1, db2_type=93, PRECISION=0, SCALE=6, Maxlen=0, Described <- execute= -1 at ./count line 161 via at ./count line 36 -> fetchrow_arrayref for DBD::DB2::st (DBI::st=HASH(0x94f9930)~0x94f98d0) thr#932d008 !! info: '' 'SQL_NO_DATA returned from Diagnostic Information. There might be no diagnostic records for this handle. Please see Infocentre for more details!!' (err#2) <- fetchrow_arrayref= undef row-1 at ./count line 163 via at ./count line 36 !! info: '' CLEARED by call to finish method -> finish for DBD::DB2::st (DBI::st=HASH(0x94f9930)~0x94f98d0) thr#932d008 <- finish= 1 at ./count line 165 via at ./count line 36 -> DESTROY for DBD::DB2::st (DBI::st=HASH(0x94f98d0)~INNER) thr#932d008 <- DESTROY= undef at ./count line 36 via at ./count line 36 -> trace for DBD::DB2::db (DBI::db=HASH(0x94f9690)~0x94f9600 0) thr#932d008 <- trace= 5 at ./count line 37 I don't know what could have changed in DBI or IBM DB2, but such an error would have been fixed long time ago. Empty result is a frequent occurrence, this must be something new. Please, keep me up-to-date and let me know if you need something or discover something. David
Subject: dbd-db2-1.76-segv.patch
diff -ru DBD-DB2-1.76/dbdimp.c DBD-DB2-1.76-EAbIPE/dbdimp.c --- DBD-DB2-1.76/dbdimp.c 2009-11-28 10:07:57.000000000 +0100 +++ DBD-DB2-1.76-EAbIPE/dbdimp.c 2010-01-08 21:42:34.594365191 +0100 @@ -93,6 +93,7 @@ message = msgBuffer; } else { err = ""; + message = ""; sqlcode = returnCode; strcpy( (char*)sqlstate, "00000" ); if(DBIc_TRACE_LEVEL(imp_xxh) >= 3){
From: dave [...] awk.cz
Debug outputs attached to preserve formatting.
Subject: dbd-segv.txt
Program received signal SIGSEGV, Segmentation fault. strlen () at ../sysdeps/i386/i486/strlen.S:69 69 ../sysdeps/i386/i486/strlen.S: No such file or directory. in ../sysdeps/i386/i486/strlen.S Current language: auto The current source language is "auto; currently asm". (gdb) bt #0 strlen () at ../sysdeps/i386/i486/strlen.S:69 #1 0xb7cab776 in set_err_char (h=0x8354918, imp_xxh=0x84397f8, err_c=0xb7c76e47 "", err_i=100, errstr=0x0, state=0xbfffec3e "00000", method=0x0) at DBI.xs:604 #2 0xb7c6c4ea in setErrorFromDiagRecInfo (perlHandle=<value optimized out>, handleType=<value optimized out>, handle=65537, err=0xb7c76e47 "") at dbdimp.c:112 #3 0xb7c6c693 in diagnoseError (perlHandle=0x8354918, handleType=9376, handle=65537, rc=100, what=0xb7c76dd8 "Fetch Failed") at dbdimp.c:54 #4 0xb7c72ee7 in db2_st_fetch (sth=0x8354918, imp_sth=0x84397f8) at dbdimp.c:2539 #5 0xb7c67cc7 in XS_DBD__DB2__st_fetchrow_arrayref (my_perl=0x8188008, cv=0x8291950) at DB2.xs:399 #6 0xb7cb9299 in XS_DBI_dispatch (my_perl=0x8188008, cv=0x8326040) at DBI.xs:3292 #7 0x080b12c0 in Perl_pp_entersub () #8 0x080af688 in Perl_runops_standard () #9 0x080adbb2 in perl_run () #10 0x08063ffd in main ()
Subject: dbd-trace.txt
DBI::db=HASH(0x94f9600) trace level set to 0x0/5 (DBI @ 0x0/0) in DBI 1.609-ithread (pid 10458) DB2: 2009-11-20-06.00.00 - 2009-11-21-06.00.00 -> prepare for DBD::DB2::db (DBI::db=HASH(0x94f9690)~0x94f9600 ' SELECT count(RPT.ACC_BODYHIST.KANR) count FROM RPT.ACC_BODYHIST WHERE RPT.ACC_BODYHIST.STATUS0 = ? AND RPT.ACC_BODYHIST.MDATUMZEIT >= TIMESTAMP( CAST(? AS TIMESTAMP) ) AND RPT.ACC_BODYHIST.MDATUMZEIT < TIMESTAMP( CAST(? AS TIMESTAMP) ) GROUP BY RPT.ACC_BODYHIST.STATUS0; ') thr#932d008 New 'DBI::st' (for DBD::DB2::st, parent=DBI::db=HASH(0x94f9600), id=undef) dbih_setup_handle(DBI::st=HASH(0x94f9930)=>DBI::st=HASH(0x94f98d0), DBD::DB2::st, 9477790, Null!) dbih_make_com(DBI::db=HASH(0x94f9600), 93542f8, DBD::DB2::st, 160, 0) thr#932d008 dbih_setup_attrib(DBI::st=HASH(0x94f98d0), Err, DBI::db=HASH(0x94f9600)) SCALAR(0x94776b0) (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), State, DBI::db=HASH(0x94f9600)) SCALAR(0x9477730) (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), Errstr, DBI::db=HASH(0x94f9600)) SCALAR(0x94776f0) (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), TraceLevel, DBI::db=HASH(0x94f9600)) 5 (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), FetchHashKeyName, DBI::db=HASH(0x94f9600)) 'NAME' (already defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), HandleSetErr, DBI::db=HASH(0x94f9600)) undef (not defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), HandleError, DBI::db=HASH(0x94f9600)) undef (not defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), ReadOnly, DBI::db=HASH(0x94f9600)) undef (not defined) dbih_setup_attrib(DBI::st=HASH(0x94f98d0), Profile, DBI::db=HASH(0x94f9600)) undef (not defined) dbd_st_prepare'd sql f65537 SELECT count(RPT.ACC_BODYHIST.KANR) count FROM RPT.ACC_BODYHIST WHERE RPT.ACC_BODYHIST.STATUS0 = ? AND RPT.ACC_BODYHIST.MDATUMZEIT >= TIMESTAMP( CAST(? AS TIMESTAMP) ) AND RPT.ACC_BODYHIST.MDATUMZEIT < TIMESTAMP( CAST(? AS TIMESTAMP) ) GROUP BY RPT.ACC_BODYHIST.STATUS0; statement = SELECT count(RPT.ACC_BODYHIST.KANR) count FROM RPT.ACC_BODYHIST WHERE RPT.ACC_BODYHIST.STATUS0 = ? AND RPT.ACC_BODYHIST.MDATUMZEIT >= TIMESTAMP( CAST(? AS TIMESTAMP) ) AND RPT.ACC_BODYHIST.MDATUMZEIT < TIMESTAMP( CAST(? AS TIMESTAMP) ) GROUP BY RPT.ACC_BODYHIST.STATUS0; imp_sth->statement= SELECT count(RPT.ACC_BODYHIST.KANR) count FROM RPT.ACC_BODYHIST WHERE RPT.ACC_BODYHIST.STATUS0 = :p1 AND RPT.ACC_BODYHIST.MDATUMZEIT >= TIMESTAMP( CAST(:p2 AS TIMESTAMP) ) AND RPT.ACC_BODYHIST.MDATUMZEIT < TIMESTAMP( CAST(:p3 AS TIMESTAMP) ) GROUP BY RPT.ACC_BODYHIST.STATUS0; scanned 3 distinct placeholders fbh 0: 'COUNT' , type 4, 11, dsize 10, p0 s154487488 out: ftype 1, indp 0, bufl 45, rlen 45 !! ERROR: '-99999' '[IBM][CLI Driver] CLI0137E Information type out of range. SQLSTATE=HY096' (err#0) <- prepare= DBI::st=HASH(0x94f9930) at ./count line 147 via at ./count line 36 !! ERROR: '-99999' CLEARED by call to execute method -> execute for DBD::DB2::st (DBI::st=HASH(0x94f9930)~0x94f98d0 'Z100' '2009-11-20-06.00.00' '2009-11-21-06.00.00') thr#932d008 bind :p1 <== 'Z100' (attribs: <no attribs>) bind :p1: db2_param_type=1, db2_c_type=1, db2_type=1, PRECISION=0, SCALE=0, Maxlen=0, Described bind :p2 <== '2009-11-20-06.00.00' (attribs: <no attribs>) bind :p2: db2_param_type=1, db2_c_type=1, db2_type=93, PRECISION=0, SCALE=6, Maxlen=0, Described bind :p3 <== '2009-11-21-06.00.00' (attribs: <no attribs>) bind :p3: db2_param_type=1, db2_c_type=1, db2_type=93, PRECISION=0, SCALE=6, Maxlen=0, Described <- execute= -1 at ./count line 161 via at ./count line 36 -> fetchrow_arrayref for DBD::DB2::st (DBI::st=HASH(0x94f9930)~0x94f98d0) thr#932d008 !! info: '' 'SQL_NO_DATA returned from Diagnostic Information. There might be no diagnostic records for this handle. Please see Infocentre for more details!!' (err#2) <- fetchrow_arrayref= undef row-1 at ./count line 163 via at ./count line 36 !! info: '' CLEARED by call to finish method -> finish for DBD::DB2::st (DBI::st=HASH(0x94f9930)~0x94f98d0) thr#932d008 <- finish= 1 at ./count line 165 via at ./count line 36 -> DESTROY for DBD::DB2::st (DBI::st=HASH(0x94f98d0)~INNER) thr#932d008 <- DESTROY= undef at ./count line 36 via at ./count line 36 -> trace for DBD::DB2::db (DBI::db=HASH(0x94f9690)~0x94f9600 0) thr#932d008 <- trace= 5 at ./count line 37
Hi David, Thanks for reporting this error. Will fix this error of passing null to DBI's SET_ERR_CHAR in the next release of the driver. Coming to error CLI0137E, if you could provide us with CLI trace when the application is run we will be able to tell more on it. To Obtain the CLI trace follow the link below http://publib.boulder.ibm.com/infocenter/db2luw/v9r5/topic/com.ibm.db2.luw.admin.trb.doc/doc/c0020795.html One more thing, you will need to update your DB2 client to minimum DB2 V8fp16 or v91fp2, as these are the minimum supported versions of DB2 client for DBD-DB2 perl driver. -- Thanks Praveen IBM OpenSource Application Development Team India Software Labs, Bangalore (India)
From: dave [...] awk.cz
Ok, thank you for taking care of this. Here's a CLI trace too. :)
Subject: 26246.txt

Message body is not shown because it is too large.

From: dave [...] awk.cz
Adding a detailed table description if you'll need to compare the data type params.
Subject: table.txt
Column Type Column Partitioning key Code name schema Type name Length Scale Nulls number sequence page Default ------------------------------ ------------------------------- ------------------------------- --------- -------- -------- ---------- ------------------- -------- ---------------------------------------- WERK SYSIBM C 2 0 No 0 0 819 SPJ SYSIBM C 4 0 No 1 0 819 KANR SYSIBM C 7 0 No 2 0 819 MDATUMZEIT SYSIBM T 10 0 No 3 0 0 WERK0 SYSIBM C 2 0 No 4 0 819 STATUS0 SYSIBM C 4 0 No 5 0 819 WERK1 SYSIBM C 2 0 Yes 6 0 819 SPJ1 SYSIBM C 4 0 Yes 7 0 819 KNR1 SYSIBM C 7 0 Yes 8 0 819 MART SYSIBM C 1 0 No 9 0 819 ' ' EINDATUMZEIT SYSIBM T 10 0 No 10 0 0 CURRENT TIMESTAMP SCHKZ SYSIBM C 1 0 No 11 0 819 ' ' LFDNR SYSIBM S 2 0 No 12 0 0 0 NRGES SYSIBM C 6 0 No 13 0 819 ' ' UMSCHL SYSIBM C 1 0 No 14 0 819 ' ' INFASV SYSIBM C 2 0 No 15 0 819 ' ' WERK2 SYSIBM C 2 0 No 16 0 819 FANLAGE2 SYSIBM C 6 0 No 17 0 819 WERK3 SYSIBM C 2 0 No 18 0 819 ANLBGR3 SYSIBM C 4 0 No 19 0 819 GERAETENAME3 SYSIBM C 8 0 No 20 0 819 GUELTIG SYSIBM C 1 0 No 21 0 819 ' ' VERSCHROTTZ SYSIBM I 4 0 No 22 0 0 0 STATUSDURCHLAUF SYSIBM I 4 0 Yes 23 0 0 STATUSDURCHLAUF_ENDTS SYSIBM T 10 0 Yes 24 0 0 MDZ_CALC SYSIBM C 1 0 No 25 0 819 'N' USER_ID SYSIBM C 20 0 Yes 26 0 819 SHIFT_ID_STATUS SYSIBM I 4 0 Yes 27 0 0
Hi David, Thanks for the traces. They were handy. As mentioned earlier, you will need to upgrade to the minimum required DB2 client level. The error you are seeing is due to a lower version of the DB2 client. Could you upgrade to the minimum required level(v8fp16 or v91fp2) of DB2 client and let me know how it goes and also if possible provide me with the cli trace for the run with the new upgraded client. -- Thanks Praveen IBM OpenSource Application Development Team India Software Labs, Bangalore (India)
Hi David, The issue is been fixed and is available in the new release 1.78 http://search.cpan.org/CPAN/authors/id/I/IB/IBMTORDB2/DBD-DB2-1.78.tar.gz -- Thanks Praveen IBM OpenSource Application Development Team India Software Labs, Bangalore (India)