|CC:||Eric Promislow <ericp [...] ActiveState.com>, Kevin Goess <cpan [...] goess.org>|
|Subject:||"panic: attempt to copy freed scalar" upon commit() or rollback()|
|Date:||Sun, 15 Mar 2015 16:50:15 -0400|
|To:||bug-DBI [...] rt.cpan.org|
|From:||Frédéric Brière <fbriere [...] fbriere.net>|
[ This bug was already filed as Perl bug #113644; my thanks to Eric Promislow and Kevin Goess for figuring out what triggers it. Merely knowing that I was not alone was of great help to my sanity. <g> ] This bug manifests itself when calling commit() or rollback() in a non-null context: $ perl bug.pl panic: attempt to copy freed scalar 903a878 to 905bfd0 at bug.pl line 52. The problem is in XS_DBI_dispatch(), lines 3889-3895, when calling STORE to set AutoCommit to 0 if the driver hasn't already done so. At this point, the return values are already on the stack, and sp has already been rewound, so they get overwritten when pushing the arguments to the STORE method. (At least, that's my understanding, as a complete XS newbie.) From what I've gathered after some playtime with gdb, this usually goes unnoticed, because in the process of call_method(), it just so happens that the last value that was pushed at the bottom of the stack was &PL_sv_yes, which was probably the original return value anyway. But in different circumstances (running under the debugger in the RT ticket, or subclassing DBI and overwriting STORE in my case), this may no longer be the case. This is also specific to drivers which don't turn off AutoCommit (e.g. mysql), leaving any other unharmed (e.g. sqlite). In any case, I have had success with incrementing/decrementing sp by outitems around this block, but I have no idea if this is the right solution, given my lack of knowledge in the matter. I trust you will know better. :) If this can help, I'm attaching a simple script that triggers this bug. However, since this requires a connection to a real MySQL server (which seemed to be a hindrance according to the comments in the RT ticket), I'm also attaching a stripped-to-the-bones hackish driver spanwed from DBD::mysql (named DBD::nysql -- I was out of imagination) with only the barest minimum needed to trigger the bug, with no outside requirements. I trust you will be able to turn this mess into a proper test case. :) -- # look for dup words perl -0777 -ne 'print "$.: doubled $_\n" while /\b(\w+)\b\s+\b\1\b/gi'
Message body is not shown because sender requested not to inline it.
Message body not shown because it is not plain text.