Apache2::Reloadが失敗する問題に対するパッチ

文章を修正しました。パッチの変更はありません。
Apache2::Reloadは、対象パッケージのシンボルを全て削除した上でリロードするようになっています。しかし、対象パッケージの外部から動的に定義されているシンボルを削除してしまうと、復元することができなくなってしまいます。DBIx::Classとか他にも色々、Class::Data::Inheritableのようなものを使っている場合は大抵この現象が起きます。

そこでApache2::Reloadに当てる動的パッチを作ってみました。このパッチを当てると、シンボルを全て削除してしまうModPerl::Util::unload_package_ppは使われなくなり、%INCからモジュール名のみが削除されるようになります。

PerlModule Apache2::Reload
PerlInitHandler Apache2::Reload
<Perl>
    use Apache2::Reload ();
    use ModPerl::Util   ();

    # hack for "Can't locate mod_perl.pm" caused by mod_perl2.pm
    delete $INC{'mod_perl.pm'};

    # hack for problem that package variable doesn't appear again.
    if ( my $handler = Apache2::Reload->can('handler') ) {
        undef *Apache2::Reload::handler;
        *Apache2::Reload::handler = sub {

            # delete from %INC instead of unload symbols
            local $ModPerl::Util::DEFAULT_UNLOAD_METHOD = sub {
                my $package = shift;
                delete $INC{ Apache2::Reload::package_to_module($package) };
            };

            # call reload process
            $handler->(@_);
        };
    }
</Perl>
  • このパッチによってシンボルの削除は行なわれなくなりますのでご注意ください。(上書きや追加は正しく行なわれます。)
  • このパッチには$INC{'mod_perl.pm'} = '/dev/null'問題に対する修正も入っています。