Callbacks Ate my Brain!!

The DBI Issues List is not one that see allot of traffic but there are few of us out there that keep an eye on and a lurk around waiting to pounce on a good one.

Most are simple newbie errors or an obscure install problem but the odd one is a real bugger and they usually start or end with a line like this;

This has been running for years and and now it doesn't work!!!


There usually follows the obligatory;

'My manager wants an answer'

and or

'this never happens with PHP'

etc.

So Martin and I began the usual work up on a problem. In this case it was with DBD::Oracle, binding with ORA_VARCHAR@TABLE

Seems this

$sth->bind_param( ':in_sourceNames', $sourceNames, { ora_type => ORA_VARCHAR2_TABLE }

Died with this error

*19:05:57 ERROR: Caught an exception from DB: DBD::Oracle::st execute
failed: called with 3443804 bind variables when 7 are needed [for
Statement..."*

Suddenly stopped working, the only symptom being it doesn't die with 1000 elements in the $sourceNames array ref, but dies when there are more than 1500 or so. Myself I have used this interface with 100K+ elements with no problems so the number did not mean much to me.

At first glace it look like a resource leek so we gave our pat answer of upgrade to the latest DBD:Oracle and DBI. Well no luck. After some more back and forth with some traces and input data, Martin noticed the error was generated from this block

static int dbdxst_bind_params

Which is unfortunate as all 'xst_' code is derived 'c' code from the 'XS' process. The sub did tell me that the code was hitting the 'all_params_hv' which part of a struc deep inside one of the 'c' '.h' files for DBD::Oracle the DBD side was correct at '7' but the DBI side was where the '3443804' comes from

So we finally traced back that the error was being created by the DBI and not the DBD, I asked if they had any high level bug catching on? If you do. Turn it off and see what happens.

They turned it off and it ran. In the end they had a number of callbacks that ran against the code one line, in particular, caught my eye;

params => $sth->FETCH( 'ParamValues' ), # WTF? - returns a reference to an array of hashes

(the #WTF was the original programmers comments)

Opps! not the normal way to get an attribute from a DBI handle.

params => $sth->{'ParamValues'},

Leak found, I guess, or not? I will have to ask Tim what the impact of calling FETCH directly on a handle is, the next time I bother him at a YAPC . Seems to me this is the same sort of problem as drinking from the far side of a glass, it works but you might get wet.

Pac-man_Plus_pacplus.png

This type of event actually has a name Kill Screen or rather a tipping point. I have seen them before with such funny solutions as upgrade to to 16 bit, then 32 and then 64 bit boxes.

Lesson learned? When the only thing that has changed in a 'call' is the size of the parameters past into it and it works stand alone then it is most likely not in the 'call' that is the problem, it is the shit that is happening before that is grinding your gears.

By the way Martin did notice this right away but out friend on the other end was a little too focused on the 'call' which was just the symptom of the bug not the bug.

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations