HHeLiBeXの日記 正道編

日々の記憶の記録とメモ‥

Net::SMTPSを使い始めたところからの悪夢⇒DLLがロードされない問題の調査方法

苦しんだ3日間の奮闘メモ。

事の始まり

PerlのNet::SMTPSモジュールを使って、GmailSMTPサーバー経由でメールを送ろうという試みを始めたところから悪夢は始まった。

プログラムのコアな部分は大まかに以下のような感じ。

sub send {
        my $self = shift;
        my ($args) = @_;
        my $from      = $args->{from};
        my $to        = $args->{to};
        my $header    = $args->{header};
        my $body      = $args->{body};

        my $config = MyConfig->new;
        $config->load();
        my $smtp = $config->getSmtpAddress();
        my $port = $config->getSmtpPort();
        my $user = $config->getSmtpUser();
        my $password = $config->getSmtpPassword();

        my $mail = Net::SMTPS->new($smtp,
            Hello => $smtp,
            Port => $port,
            doSSL => 'starttls',
            Debug => 0
        );
#       $mail->starttls();
        $mail->auth($user, $password);
        $mail->mail($from);
        $mail->to($to);
        $mail->data();
        $mail->datasend(join("\r\n", $header, $body));
        $mail->dataend();
        $mail->quit();
}

support.google.com

とか。

support.google.com

こうすればいいのか、とか。

まぁいろいろとあったが、何とかCentOS 7のVM上でNet::SMTPSを使ってGmailSMTPサーバー経由でメールを送れるようになった。

問題はここから。

悪夢の始まり

Windows環境に持ってきて、XAMPPに同梱されているPerl.exeで同じプログラムを実行すると、なぜか

Failed to open SMTPS connection: Bad file descriptor at・・

というエラーメッセージが出てメールが送れない。 printデバッグで、

require IO::Socket::SSL;

しているところで失敗しているっぽいことを突き止めたり、 SET PERL_DL_DEBUG=1 とすると、以下のようにデバッグログが出ることを知ったりする。

DynaLoader.pm loaded (. C:/xampp/perl/site/lib C:/xampp/perl/vendor/lib C:/xampp/perl/lib, C:\xampp\c\lib \xampp\c\x86_64-w64-mingw32\lib \xampp\c\lib\gcc\x86_64-w64-mingw32\8.3.0)
DynaLoader::bootstrap for Net::SSLeay (auto/Net/SSLeay/SSLeay.xs.dll)
DynaLoader::bootstrap for Digest::MD5 (auto/Digest/MD5/MD5.xs.dll)
Failed to open SMTPS connection: Bad file descriptor at ・・・

そこで、DLLのロードをしているDynaLoader.pmにprintデバッグして、 MD5.xs.dll ではなく、やはり SSLeay.xs.dll のロードに失敗していることを確認。

SSLeayと言えば libeay32.dllssleay32.dll という頭もあったのだろう。 また、以下のサイトを見てしまったのも悪夢を助長させる要因となった。

stackoverflow.com

(・・・2日後・・・)

ふと、「そもそも依存しているのはlibeay32.dllssleay32.dllじゃなかったりする?」と疑問を持ったところから急展開を見せる。

「DLL 依存性」などのキーワードで探すと、あるDLLが依存しているDLLの一覧を出力する方法を知る。

tech.mlexp.net

kazupon.org

最初、コマンドプロンプト

C:\Users\hhelibex>dumpbin /dependents C:\xampp\perl\vendor\lib\auto\Net\SSLeay\SSLeay.xs.dll
'dumpbin' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。

と言われて、あれ?と思って後者のサイトを見つけ、Visual Studio 2019をインストール&Windows OSの再起動をした。

サイトの記述に従い、Visual Studio 2019を起動し、[ツール]-[コマンドライン]-[開発者用 PowerShell]でPowerShellを起動し、コマンドを叩く。

すると、

**********************************************************************
** Visual Studio 2019 Developer PowerShell v16.11.26
** Copyright (c) 2021 Microsoft Corporation
**********************************************************************
PS C:\Users\hhelibex\source\repos> dumpbin /dependents C:\xampp\perl\vendor\lib\auto\Net\SSLeay\SSLeay.xs.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30148.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file C:\xampp\perl\vendor\lib\auto\Net\SSLeay\SSLeay.xs.dll

File Type: DLL

  Image has the following dependencies:

    msvcrt.dll
    KERNEL32.dll
    libcrypto-1_1-x64__.dll
    libssl-1_1-x64__.dll
    perl532.dll

  Summary

        1000 .CRT
        2000 .bss
        1000 .data
        1000 .edata
        8000 .idata
        3000 .pdata
        D000 .rdata
        1000 .reloc
       5E000 .text
        1000 .tls
        4000 .xdata
PS C:\Users\hhelibex\source\repos>

libcrypto-1_1-x64__.dlllibssl-1_1-x64__.dll !?初めて見たぞ。

とりあえずググる。そして、いろいろとダウンロードして名前を変更して(アンダースコア2つ「__」が入っていないので)、順番に試す。 ダメ。

途方に暮れながら、何気なくPC内を探す。 ・・ なんかある!?

C:\Users\hhelibex> dir C:\xampp\apache\bin
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は 4006-07DE です

 C:\Users\hhelibex\xampp\apache\bin のディレクトリ

2023/05/23  20:33    <DIR>          .
2023/05/23  20:33    <DIR>          ..
2023/03/07  22:22            98,816 ab.exe
2023/03/07  22:22           110,592 abs.exe
2023/03/07  22:22            43,008 ApacheMonitor.exe
2023/03/07  22:22            19,456 apr_crypto_openssl-1.dll
2023/03/07  22:22            31,232 apr_dbd_odbc-1.dll
2023/03/07  22:22            14,848 apr_ldap-1.dll
2022/05/30  19:58           215,352 curl-ca-bundle.crt
2019/02/06  15:58         4,110,456 curl.exe
2023/03/07  22:25             9,192 dbmmanage.pl
2023/03/07  22:22           101,888 htcacheclean.exe
2023/03/07  22:22           124,416 htdbm.exe
2023/03/07  22:22            86,016 htdigest.exe
2023/03/07  22:22           118,784 htpasswd.exe
2023/03/07  22:24            30,720 httpd.exe
2023/03/07  22:22            65,536 httxt2dbm.exe
2023/05/23  20:33    <DIR>          iconv
2023/03/15  03:30        30,422,016 icudt71.dll
2023/03/15  03:30         3,031,552 icuin71.dll
2023/03/15  03:30            60,928 icuio71.dll
2023/03/15  03:30         2,253,312 icuuc71.dll
2021/09/12  18:59            55,808 jansson.dll
2023/03/07  22:20           215,552 libapr-1.dll
2023/03/07  22:20            36,864 libapriconv-1.dll
2023/03/07  22:20           294,912 libaprutil-1.dll
2023/02/09  21:49         3,445,248 libcrypto-1_1-x64.dll     ⇐☆☆☆
2019/02/06  15:58         1,020,536 libcurl.dll
2023/03/07  22:21           459,776 libhttpd.dll
2023/03/15  03:30           209,920 libsasl.dll
2023/03/15  03:30           380,928 libssh2.dll
2023/02/09  21:50           689,664 libssl-1_1-x64.dll       ⇐☆☆☆
2022/11/02  01:03         1,373,696 libxml2.dll
2023/03/07  22:22            58,368 logresolve.exe
2019/04/05  23:28           184,320 lua52.dll
2023/03/07  22:16           156,160 nghttp2.dll
2023/02/09  21:51           550,912 openssl.exe
2021/08/23  23:32           400,896 pcre.dll
2023/01/12  18:44           564,224 pcre2-8.dll
2012/04/17  02:30            61,440 pv.exe
2023/03/07  22:22            78,848 rotatelogs.exe
2023/03/07  22:22            18,432 wintty.exe
2022/11/02  01:06            89,600 zlib1.dll
              40 個のファイル          51,294,224 バイト
               3 個のディレクトリ  415,936,548,864 バイトの空き領域
C:\Users\hhelibex> 

ファイル名はちょっと違うけど、それっぽい! 早速PATHを通して実行してみる。。。やっぱりダメ。じゃあ、コピーして名前を変更して実行。 ・・・ 動いた!!!

じゃあ、PATHを通さずに、libcrypto-1_1-x64__.dlllibssl-1_1-x64__.dllだけコピーして・・ダメ。 まぁ、とりあえず動く方法が見つかって、ようやく一安心したところで、詳細を調べてみた。

先ほどのDLLの依存関係の続き。

PS C:\Users\hhelibex\source\repos> dumpbin /dependents C:\Users\hhelibex\SMTPServer\libcrypto-1_1-x64__.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30148.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file C:\Users\hhelibex\SMTPServer\libcrypto-1_1-x64__.dll

File Type: DLL

  Image has the following dependencies:

    WS2_32.dll
    ADVAPI32.dll
    USER32.dll
    bcrypt.dll
    KERNEL32.dll
    VCRUNTIME140.dll
    api-ms-win-crt-stdio-l1-1-0.dll
    api-ms-win-crt-convert-l1-1-0.dll
    api-ms-win-crt-string-l1-1-0.dll
    api-ms-win-crt-time-l1-1-0.dll
    api-ms-win-crt-utility-l1-1-0.dll
    api-ms-win-crt-runtime-l1-1-0.dll
    api-ms-win-crt-filesystem-l1-1-0.dll
    api-ms-win-crt-heap-l1-1-0.dll
    api-ms-win-crt-environment-l1-1-0.dll

  Summary

        1000 .00cfg
        8000 .data
        3000 .idata
       1C000 .pdata
       CF000 .rdata
        8000 .reloc
        1000 .rsrc
      252000 .text
PS C:\Users\hhelibex\source\repos> dumpbin /dependents C:\Users\hhelibex\SMTPServer\libssl-1_1-x64__.dll
Microsoft (R) COFF/PE Dumper Version 14.29.30148.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file C:\Users\hhelibex\SMTPServer\libssl-1_1-x64__.dll

File Type: DLL

  Image has the following dependencies:

    libcrypto-1_1-x64.dll     ⇐☆☆☆
    KERNEL32.dll
    VCRUNTIME140.dll
    api-ms-win-crt-time-l1-1-0.dll
    api-ms-win-crt-string-l1-1-0.dll
    api-ms-win-crt-utility-l1-1-0.dll
    api-ms-win-crt-runtime-l1-1-0.dll
    api-ms-win-crt-convert-l1-1-0.dll
    api-ms-win-crt-stdio-l1-1-0.dll

  Summary

        1000 .00cfg
        5000 .data
        6000 .idata
        6000 .pdata
       23000 .rdata
        2000 .reloc
        1000 .rsrc
       74000 .text
PS C:\Users\hhelibex\source\repos>

・・おまえか! libssl-1_1-x64__.dlllibcrypto-1_1-x64.dll に依存している。 だからlibcrypto-1_1-x64__.dlllibssl-1_1-x64__.dllだけあってもダメで、同じ内容でファイル名だけ違う libcrypto-1_1-x64.dll がいないとダメなのか。

案の定、ファイルを3つ用意したら、PATHを通す必要もなく動いた。 あとは、これをWindowsサービス登録する形になるから、その場合にどうなるかだが、それはこれから調査。

反省

「SSLeay」と言えば「libeay32.dllとssleay32.dll」という思い込みから悪夢が始まり、3日間くらい浪費したので、思い込みは良くない。 でも、もう少しエラーメッセージを改善してほしい。依存しているけど見つからないライブラリをエラーメッセージに載せてくれればここまで悩まずに済んだんだけどな。