Perl 本体が落ちる
Windows 7 上で Perl を実行すると Perl.exe が初めてクラッシュした。思い当たることがなく、同じスクリプトを FreeBSD 上で実行すると Perl がクラッシュしてコアダンプを吐き出した。
% tail -f /var/log/messages Nov 18 13:43:49 myhost kernel: pid 83986 (perl5.12.4), uid 1001: exited on signal 11 (core dumped)
Windows 7 も同様にイベントログにエラーが出されている。
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <Events> <Event xmlns='http://schemas.microsoft.com/win/2004/08/events/event'> <System><Provider Name='Application Error'/> <EventID Qualifiers='0'>1000</EventID> <Level>2</Level> <Task>100</Task> <Keywords>0x80000000000000</Keywords> <TimeCreated SystemTime='2011-11-18T03:17:59.000000000Z'/> <EventRecordID>11391</EventRecordID> <Channel>Application</Channel> <Computer>MY-PC.local</Computer> <Security/></System> <EventData> <Data>perl.exe</Data> <Data>5.12.3.1204</Data> <Data>4d531b74</Data> <Data>mysql.dll</Data> <Data>0.0.0.0</Data> <Data>4e336678</Data> <Data>c0000409</Data> <Data>000000000000dde9</Data> <Data>1388</Data> <Data>01cca5a0a81a80ef</Data> <Data>C:\Perl64\bin\perl.exe</Data> <Data>C:\Perl64\site\lib\auto\DBD\mysql\mysql.dll</Data> <Data>e9f97a7f-1193-11e1-aaf1-f04da2dbd192</Data> </EventData> <RenderingInfo Culture='ja-JP'> <Message>障害が発生しているアプリケーション名: perl.exe、バージョン: 5.12.3.1204、タイム スタンプ: 0x4d531b74 障害が発生しているモジュール名: mysql.dll、バージョン: 0.0.0.0、タイム スタンプ: 0x4e336678 例外コード: 0xc0000409 障害オフセット: 0x000000000000dde9 障害が発生しているプロセス ID: 0x1388 障害が発生しているアプリケーションの開始時刻: 0x01cca5a0a81a80ef 障害が発生しているアプリケーション パス: C:\Perl64\bin\perl.exe 障害が発生しているモジュール パス: C:\Perl64\site\lib\auto\DBD\mysql\mysql.dll レポート ID: e9f97a7f-1193-11e1-aaf1-f04da2dbd192 </Message> <Level>エラー</Level> <Task>アプリケーション クラッシュ イベント</Task> <Opcode>情報</Opcode> <Channel></Channel> <Provider></Provider> <Keywords> <Keyword>クラシック</Keyword> </Keywords> </RenderingInfo> </Event> </Events>
mysql.dll の名称が出ていたので、DBD::MYSQL のアップデートを施しても、クラッシュが治らない。
ほぼ半日をかけたところで、ソースコードに誤りがあることに気が付いた。プリペアードステートメントにバインドするパラメータの型付けが間違っていた。
my $sth = $dbh->prepare('INSERT INTO `my_db` (`timestamp`, `message`) VALUES (?, ?);'); $sth->bind_param(1, $timestamp, SQL_VARCHAR); $sth->bind_param(2, $strings, SQL_INTEGER); eval{ $sth->execute }; ...
というようにINT型である `timestamp` には SQL_VARCHA を指定し、`message` には SQL_INTEGER を指定していたためだった。
指定を間違えていた場合、warn や die が発生するのではなく、Perl そのものがクラッシュするとは思わなかった。
初めての経験とはいえ、これまでよくも同じような間違えをこれまでしなかったものだと思った。