blog20100901

2013/08/20 - プログラミング言語 Perl にまつわる etc. - Perl monger
参考 : perldoc, perldoc.jp, search.cpan.org, perldoc.perl.org ...
「 初めての Perl 第 6 版 」(オライリー・ジャパン発行 ISBN978-4-87311-567-2) 」
「 続・初めての Perl 改訂版 」(オライリー・ジャパン発行 ISBN4-87311-305-9) 」
「 Effective Perl 第 2 版 」(翔泳社発行 ISBN978-4-7981-3981-4) 」 ... etc,.

Perl Perl_7 mod_perl 翻訳 Web Server

Perl mp2 翻訳 mod_perl ハンドラとスクリプトを書く (d190)

目次 - Perl Index


Theme



Perl について、復習を兼ねて断片的な情報を掲載して行く連載その d190 回。

今回は、「 mod_perl Home / The mod_perl Web Site / Documentation / mod_perl 2.0 Documentation / User's guide / Part III: Coding / Writing mod_perl Handlers and Scripts 」を翻訳して確認します。

正確な内容は 原文 を確認してください。誤解や誤訳がある場合はご指摘ください。





説明 : Description


This chapter covers the mod_perl coding specifics, different from normal Perl coding. Most other perl coding issues are covered in the perl manpages and rich literature.

このチャプタは普通の Perl コーディングとは異なる, mod_perl コーディングの仕様をカバーします。perl コーディングの他の問題のほとんどは perl man ページとリッチな文献でカバーされています。


前提条件 : Prerequisites




メソッドがある場所 : Where the Methods Live


mod_perl 2.0 has all its methods spread across many modules. In order to use these methods the modules containing them have to be loaded first. If you don't do that mod_perl will complain that it can't find the methods in question. The module ModPerl::MethodLookup can be used to find out which modules need to be used.

mod_perl 2.0 はそのすべてのメソッドが多くのモジュールに分散されています。これらのメソッドを使うためにはそれらを含むモジュールを最初にロードしなければなりません。もしあなたがそうしないなら mod_perl は該当するメソッドが見つからないと文句を言います。モジュール ModPerl::MethodLookup は使いたいモジュールを見つけ出すために使うことができます。


テクニック : Techniques




メソッドハンドラ : Method Handlers


In addition to function handlers method handlers can be used. Method handlers are useful when you want to write code that takes advantage of inheritance. To make the handler act as a method under mod_perl 2, use the method attribute.

See the Perl attributes manpage for details on the attributes syntax (perldoc attributes).

For example:

ファンクションハンドラに加えてメソッドハンドラを使えます。メソッドハンドラはあなたが継承を活用するコードを書きたい時に便利です。mod_perl 2 でメソッドのようにハンドラを機能させるには, method アトリビュートを使います。

アトリビュートのシンタックスの詳細は Perl attributes man ページを参照してください (perldoc attributes)。

例えば:

package Bird::Eagle;
@ISA = qw(Bird);

sub handler : method {
my ($class_or_object, $r) = @_;
...;
}

sub new { bless {}, __PACKAGE__ }

and then register it as:

それからこれをこのように登録します:

PerlResponseHandler Bird::Eagle

the :method attribute is not required.

In the preceding configuration example, the handler() method will be called as a class (static) method.

Also, you can use objects created at startup to call methods. For example:

:method アトリビュートは必須ではありません。

前述の構成例で, handler() メソッドはクラス (static) メソッドとして呼ばれます。

また, あなたはメソッドを呼ぶためにスタートアップで作成されたオブジェクトを使えます。例えば:

<Perl>
use Bird::Eagle;
$Bird::Global::object = Bird::Eagle->new();
</Perl>
...
PerlResponseHandler $Bird::Global::object->handler

In this example, the handler() method will be called as an instance method on the global object $Bird::Global::object.

この例では, handler() メソッドはグローバルオブジェクト $Bird::Global::object でのインスタンスメソッドとして呼ばれます。


クリーンアップ : Cleaning up


It's possible to arrange for cleanups to happen at the end of various phases. One can't rely on END blocks to do the job, since these don't get executed until the interpreter quits, with an exception to the Registry handlers.

さまざまなフェーズの最後でクリーンアップが起きるように手配することが可能です。ジョブを行うために END ブロックに頼ることはできません, それらはインタプリタが終了するまで実行されないためです, Registry ハンドラは例外です。
Module authors needing to run cleanups after each HTTP request, should use PerlCleanupHandler.

各 HTTP リクエストの後でクリーンアップの実行を必要とするモジュールの作者は, PerlCleanupHandler を使う必要があります。
Module authors needing to run cleanups at other times can always register a cleanup callback via cleanup_register on the pool object of choice. Here are some examples of its usage:

他の時点でクリーンアップの実行を必要とするモジュール作者は選択したプールオブジェクトの cleanup_register を介してクリーンアップコールバックをいつでも登録できます。こちらがその使用法の例です:
To run something at the server shutdown and restart use a cleanup handler registered on server_shutdown_cleanup_register() in startup.pl:

サーバのシャットダウンとリスタートで何かを実行するために startup.pl の server_shutdown_cleanup_register() で登録されたクリーンアップハンドラを使えます:

#PerlPostConfigRequire startup.pl
use Apache2::ServerUtil ();
use APR::Pool ();

warn "parent pid is $$\n";
Apache2::ServerUtil::server_shutdown_cleanup_register((\&cleanup);
sub cleanup { warn "server cleanup in $$\n" }

This is usually useful when some server-wide cleanup should be performed when the server is stopped or restarted.

To run a cleanup at the end of each connection phase, assign a cleanup callback to the connection pool object:

これは通常サーバがストップまたはリスタートしたときにサーバ全体のクリーンアップを実行しなければならない場合に便利です。

各コネクションフェーズの最後でクリーンアップを実行するには, コネクションプールのオブジェクトにクリーンアップコールバックをアサインします:

use Apache2::Connection ();
use APR::Pool ();

my $pool = $c->pool;
$pool->cleanup_register(\&my_cleanup);
sub my_cleanup { ... }

You can also create your own pool object, register a cleanup callback and it'll be called when the object is destroyed:

あなたはあなた独自のプールオブジェクトを作成して, クリーンアップコールバックを登録しオブジェクトが破棄された時にそれが呼ばれるようにすることもできます。

use APR::Pool ();

{
my @args = 1..3;
my $pool = APR::Pool->new;
$pool->cleanup_register(\&cleanup, \@args);
}

sub cleanup {
my @args = @{ +shift };
warn "cleanup was called with args: @args";
}

In this example the cleanup callback gets called, when $pool goes out of scope and gets destroyed. This is very similar to OO DESTROY method.

この例では $pool がスコープ外になり破棄された時に, クリーンアップコールバックが呼ばれます。これは OO (# オブジェクト指向の) DESTORY メソッドにとても似ています。


いい感じのツールキット : Goodies Toolkit




環境変数 : Environment Variables


mod_perl sets the following environment variables:

mod_perl は次の環境変数をセットします:


  • $ENV{MOD_PERL} - is set to the mod_perl version the server is running under. e.g.:

    $ENV{MOD_PERL} - これはサーバが実行している mod_perl のバージョンをセットします.e.g:

    mod_perl/2.000002

    If $ENV{MOD_PERL} doesn't exist, most likely you are not running under mod_perl.

    もし $ENV{MOD_PERL} が存在していないなら, あなたは mod_perl のもとでは実行していない可能性が高いです。

    die "I refuse to work without mod_perl!" unless exists $ENV{MOD_PERL};

    However to check which version is used it's better to use the following technique:

    しかし使われているバージョンをチェックするには次のテクニックを使うのがベターです:

    use mod_perl;
    use constant MP2 => ( exists $ENV{MOD_PERL_API_VERSION} and
    $ENV{MOD_PERL_API_VERSION} >= 2 );

    # die "I want mod_perl 2.0!" unless MP2;



mod_perl passes (exports) the following shell environment variables (if they are set) :

mod_perl は (もしこれらがセットされていれば) 次のシェル環境変数を渡します (exports) :


  • PATH - Executables search path.

    PATH - 実行可能ファイルの検索パス。


  • TZ - Time Zone.

    TZ - タイムゾーン。


Any of these environment variables can be accessed via %ENV.

これらの環境変数はいずれも %ENV を介してアクセスできます。


MPM はスレッド化されてる ? : Threaded MPM or not?


If the code needs to behave differently depending on whether it's running under one of the threaded MPMs, or not, the class method Apache2::MPM->is_threaded can be used. For example:

コードをスレッド MPM のもとで実行しているか, そうでないかによって異なる振る舞いにする必要があるなら, クラスメソッド Apache2::MPM->is_threaded が使えます。例えば:

use Apache2::MPM ();
if (Apache2::MPM->is_threaded) {
require APR::OS;
my $tid = APR::OS::current_thread_id();
print "current thread id: $tid (pid: $$)";
}
else {
print "current process id: $$";
}

This code prints the current thread id if running under a threaded MPM, otherwise it prints the process id.

このコードはスレッド化された MPM のもとで実行していると現在のスレッド id を出力し, そうでなければプロセス id を出力します。


MPM 固有のコードを書く : Writing MPM-specific Code


If you write a CPAN module it's a bad idea to write code that won't run under all MPMs, and developers should strive to write a code that works with all mpms. However it's perfectly fine to perform different things under different mpms.

If you don't develop CPAN modules, it's perfectly fine to develop your project to be run under a specific MPM.

もしあなたが CPAN モジュールを書くならすべての MPM のもとで実行できないコードを書くのは悪いアイデアで, 開発者はすべての mpm で機能するコードを書くように努めなければなりません。しかし異なる mpm で異なることを実行するのはまったくかまいません。

もしあなたが CPAN モジュールを開発しないなら, 固有の MPM のもとで実行するあなたのプロジェクトを開発することはまったくかまいません。

use Apache2::MPM ();
my $mpm = lc Apache2::MPM->show;
if ($mpm eq 'prefork') {
# prefork-specific code
}
elsif ($mpm eq 'worker') {
# worker-specific code
}
elsif ($mpm eq 'winnt') {
# winnt-specific code
}
else {
# others ...
}



コードの開発のニュアンス : Code Developing Nuances




Apache2::Reload での修正されたモジュールの自動ローディング : Auto-Reloading Modified Modules with Apache2::Reload


META: need to port Apache2::Reload notes from the guide here. but the gist is:

META: ここにガイドから Apache2::Reload のノートを移植しないといけない。しかし要点はつぎのとおり:

PerlModule Apache2::Reload
PerlInitHandler Apache2::Reload
#PerlPreConnectionHandler Apache2::Reload
PerlSetVar ReloadAll Off
PerlSetVar ReloadModules "ModPerl::* Apache2::*"

Use:

PerlInitHandler Apache2::Reload

if you need to debug HTTP protocol handlers. Use:

あなたが HTTP プロトコルハンドラのデバッグが必要な場合。使います:

PerlPreConnectionHandler Apache2::Reload

for any handlers.

任意のハンドラ用です。
Though notice that we have started to practice the following style in our modules:

ただし私たちは私たちのモジュールで次のスタイルの実践を開始していることに注意してください:

package Apache2::Whatever;

use strict;
use warnings FATAL => 'all';

FATAL => 'all' escalates all warnings into fatal errors. So when Apache2::Whatever is modified and reloaded by Apache2::Reload the request is aborted. Therefore if you follow this very healthy style and want to use Apache2::Reload, flex the strictness by changing it to:

FATAL => 'all' はすべての警告を致命的なエラーにエスカレートします。ですから Apache2::Whatever が修正されて Apache2::Reload によりリロードされるとリクエストは中止されます。したがってもしあなたがこのとても健全なスタイルをフォローして Apache2::Reload を使いたいなら, このように変更して厳密さを緩和します:

use warnings FATAL => 'all';
no warnings 'redefine';

but you probably still want to get the redefine warnings, but downgrade them to be non-fatal. The following will do the trick:

しかしあなたは redefine を致命的なではないものにダウングレードしつつ, その警告は取得したいかもしれません。次のトリックでできます:

use warnings FATAL => 'all';
no warnings 'redefine';
use warnings 'redefine';

Perl 5.8.0 allows to do all this in one line:

Perl 5.8.0 はこれらすべてを 1 行でできます:

use warnings FATAL => 'all', NONFATAL => 'redefine';

but if your code may be used with older perl versions, you probably don't want to use this new functionality.

Refer to the perllexwarn manpage for more information.

しかしもしあなたのコードがより古い perl バージョンで使われるなら, あなたはこの新しい機能を使わないほうがよいでしょう。

詳細は perllexwarn man ページを参照してください。


Apache の問題とインテグレーション : Integration with Apache Issues


In the following sections we discuss the specifics of Apache behavior relevant to mod_perl developers.

次のセクションで私たちは mod_perl 開発者に関連する Apache の詳細な動作を論じます。


HTTP レスポンスヘッダ : HTTP Response Headers




HTTP レスポンスヘッダの生成 : Generating HTTP Response Headers


The best approach for generating HTTP response headers is by using the mod_perl API. Some common headers have dedicated methods, others are set by manipulating the headers_out table directly.

For example to set the Content-type header you should call $r->content_type:

HTTP レスポンスヘッダを生成するためのベストアプローチは mod_perl API を使うことです。いくつかの一般的なヘッダは専用のメソッドで, 他は直接 headers_out テーブルを操作してセットします。

例えば Content-type ヘッダをセットするためにあなたは $r->content_type を呼べます:

use Apache2::RequestRec ();
$r->content_type('text/html');

To set a custom header My-Header you should call:

カスタムハンドラ My-Header を set するためにあなたはこれを呼べます:

use Apache2::RequestRec ();
use APR::Table;
$r->headers_out->set(My-Header => "SomeValue");

If you are inside a registry script you can still access the Apache2::RequestRec object.

あなたがレジストリスクリプトの内側にいる場合でもあなたはまだ Apache2::RequestRec オブジェクトにアクセスできます
Howerever you can choose a slower method of generating headers by just printing them out before printing any response. This will work only if PerlOptions +ParseHeaders is in effect. For example:

けれどもあなたはレスポンスを出力する前にヘッダを出力することでそれらを生成するより遅い手法も選択できます。これは PerlOptions +ParseHeaders が有効な場合のみで機能します。例えば:

print "Content-type: text/html\n";
print "My-Header: SomeValue\n";
print "\n";

This method is slower since Apache needs to parse the text to identify certain headers it needs to know about. It also has several limitations which we will now discuss.

このメソッドは Apache が知る必要のある特定のヘッダを識別するためのテキストのパースを必要とするので遅くなります。それは私たちが論じるいくつかの制限ももっています。
When using this approach you must make sure that the STDOUT filehandle is not set to flush the data after each print (which is set by the value of a special perl variable $|). Here we assume that STDOUT is the currently select()ed filehandle and $| affects it.

For example this code won't work:

このアプローチを使うときあなたは STDOUT ファイルハンドルが各出力の後でデータのフラッシュ (これは特別な perl 変数 $| の値によりセットされます) がセットされていないことを確認しなければなりません。ここで私たちは STDOUT が現在の select() されたファイルハンドルでそれに $| がそれに影響していると仮定しています。

例えばこのコードは機能しません:

local $| = 1;
print "Content-type: text/html\n";
print "My-Header: SomeValue\n";
print "\n";

Having a true $| causes the first print() call to flush its data immediately, which is sent to the internal HTTP header parser, which will fail since it won't see the terminating "\n\n". One solution is to make sure that STDOUT won't flush immediately, like so:

true の $| をもっているので最初の print() のコールでそのデータが即時フラッシュされることになり, 内部の HTTP ヘッダパーサに送信されますが, これは終端の "\n\n" が見えないために失敗します。ひとつの解決策は STDOUT がすぐにフラッシュしないことを確実にしておくことで, このように:

local $| = 0;
print "Content-type: text/html\n";
print "My-Header: SomeValue\n";
print "\n";

Notice that we local()ize that change, so it won't affect any other code.

私たちは local() してそれを変更しているので, それが他のコードに影響しないことに注目してください。
If you send headers line by line and their total length is bigger than 8k, you will have the header parser problem again, since mod_perl will flush data when the 8k buffer gets full. In which case the solution is not to print the headers one by one, but to buffer them all in a variable and then print the whole set at once.

もしあなたが 1 行ずつヘッダを送信しそれらの全体の長さが 8k よりも大きい場合, mod_perl は 8k のバッファがフルになるとデータをフラッシュするので, あなたは再びヘッダパーサの問題をもつことになります。この場合の解決策は 1 つずつヘッダを出力せずに, それらをすべて変数にバッファしてそれから 1 度にそのセット全体を出力します。
Notice that you don't have any of these problems with mod_cgi, because it ignores any of the flush attempts by Perl. mod_cgi simply opens a pipe to the external process and reads any output sent from that process at once.

あなたは mod_cgi ではこれらの問題をもたないことに注意して下さい, Perl によってすべてのフラッシュの施行が無視されるからです。mod_cgi はシンプルに外部プロセスへのパイプをオープンしそのプロセスから送信された出力を 1 度で読みます。
If you use $r to set headers as explained at the beginning of this section, you won't encounter any of these problems.

もしあなたがこのセクションの最初に説明したようにハンドラのセットに $r を使うなら, あなたはこれらの問題とエンカウントすることはありません。
Finally, if you don't want Apache to send its own headers and you want to send your own set of headers (non-parsed headers handlers) use the $r->assbackwards method. Notice that registry handlers will do that for you if the script's name start with the nph- prefix.

最後に, もしあなたが Apache がそれ独自のヘッダを送信することを望まずにあなたがあなた独自のヘッダのセット (non-parsed のヘッダハンドラ) を送信したいなら $r->assbackwards メソッドを使います。スクリプトの名前が nph- プレフィクスではじまっているとレジストリハンドラがあなたのためにそれを行うことに注意して下さい


HTTP レスポンスヘッダの出力を強制する : Forcing HTTP Response Headers Out


Apache 2.0 doesn't provide a method to force HTTP response headers sending (what used to be done by send_http_header() in Apache 1.3). HTTP response headers are sent as soon as the first bits of the response body are seen by the special core output filter that generates these headers. When the response handler sends the first chunks of body it may be cached by the mod_perl internal buffer or even by some of the output filters. The response handler needs to flush the output in order to tell all the components participating in the sending of the response to pass the data out.

Apache 2.0 は HTTP レスポンスヘッダの送信を強制するメソッド (Apache 1.3 では send_http_headr() を使って行われていたもの) の提供は行っていません。HTTP レスポンスヘッダはレスポンスボディの最初のビットがこれらのヘッダを生成する特別なコアの出力フィルタによって確認されるとすぐに送信されます。レスポンスハンドラがボディの最初のチャンク (# ひと塊り) を送信するときそれは mod_perl の内部バッファまたはいくつかの出力フィルタによってキャッシュされるかもしれません。レスポンスハンドラはレスポンスの送信に参加するすべてのコンポーネントにデータを渡すように伝えるために出力のフラッシュを必要とします。
For example if the handler needs to perform a relatively long-running operation (e.g. a slow db lookup) and the client may timeout if it receives nothing right away, you may want to start the handler by setting the Content-Type header, following by an immediate flush:

例えばハンドラが比較的長い時間走る操作 (e.g. 遅い db の検索) の実行を必要としていてクライアントがすぐに何も受信しない場合にタイムアウトするかもしれない場合, あなたは Content-Type ハンドラの設定によりハンドラをスタートさせることもできます, 次の即時フラッシュによって:

sub handler {
my $r = shift;
$r->content_type('text/html');
$r->rflush; # send the headers out

$r->print(long_operation());
return Apache2::Const::OK;
}

If this doesn't work, check whether you have configured any third-party output filters for the resource in question. Improperly written filter may ignore the command to flush the data.

もしこれが機能しないなら, あなたが何か該当のリソースのためにサードパーティの出力フィルタを構成していないかをチェックします。不適切に書かれたフィルタはデータフラッシュのコマンドを無視するかもしれません。


HTTP レスポンスボディの送信 : Sending HTTP Response Body


In mod_perl 2.0 a response body can be sent only during the response phase. Any attempts to do that in the earlier phases will fail with an appropriate explanation logged into the error_log file.

This happens due to the Apache 2.0 HTTP architecture specifics. One of the issues is that the HTTP response filters are not setup before the response phase.

mod_perl 2.0 でレスポンスボディはレスポンスフェーズの間でのみ送信することができます。これより早いフェーズでそれをしようとすると error_log ファイルに適切な説明が記録されて失敗します。

Apache 2.0 の HTTP アーキテクチャの仕様を原因としてこれが発生します。この問題の 1 つは HTTP レスポンスフィルタがレスポンスフェーズの前にセットアップされていないことです。


シグナルハンドラを使う : Using Signal Handlers


3rd party Apache 2 modules should avoid using code relying on signals. This is because typical signal use is not thread-safe and modules which rely on signals may not work portably. Certain signals may still work for non-threaded mpms. For example alarm() can be used under prefork MPM, but it won't work on any other MPM. Moreover the Apache developers don'tq guarantee that the signals that currently happen to work will continue to do so in the future Apache releases. So use them at your own risk.

3rd パーティの Apache2 モジュールはシグナルに頼るコードを使うのは避けなければなりません。これは典型的にシグナルの利用がスレッドセーフではなくシグナルに頼るモジュールは移植ができないかもしれないからです。特定のシグナルは非スレッド化 mpm でも機能するかもしれません。例えば alarm() は prefork MPM のもとで使われますが, それは他の MPM では機能しません。そのうえ Apache 開発陣は現在機能しているシグナルが将来の Apache でリリースでもそうであり続けることを保証しません。ですからあなたの自己責任でそれらを使ってください。
It should be possible to rework the code using signals to use an alternative solution, which works under threads. For example if you were using alarm() to trap potentially long running I/O, you can modify the I/O logic for select/poll usage (or if you use APR I/O then set timeouts on the apr pipes or sockets). For example, Apache 1.3 on Unix made blocking I/O calls and relied on the parent process to send the SIGALRM signal to break it out of the I/O after a timeout expired. With Apache 2.0, APR support for timeouts on I/O operations is used so that signals or other thread-unsafe mechanisms are not necessary.

スレッドのもとで機能する代替のソリューションを使うために, シグナルを使ったコードを改訂することができるはずです。例えばあなたが長く走る可能性がある I/O をトラップするために alarm() を使っているなら, あなたは選択/ポーリングのために利用する (またはあなたが APR I/O を使っていて apr パイプかソケットでタイムアウトをセットしている) I/O ロジックを修正できます。例えば, Unix での Apache 1.3 は I/O コールをブロックするようにしてタイムアウトが期限切れした後に I/O から抜け出す SIGALRM シグナルの送信を parent (# 親) プロセスに頼っていました。Apache 2.0 では, I/O 操作でのタイムアウトのために APR サポートが使われるのでシグナルや他のスレッドセーフでないメカニズムは必須ではありません。
CPU timeout handling is another example. It can be accomplished by modifying the computation logic to explicitly check for the timeout at intervals.

CPU タイムアウトの処理は他の事例です。それは定期でタイムアウトを明示的にチェックするように計算ロジックを変更することで成し遂げることができます。
Talking about alarm() under prefork mpm, POSIX signals seem to work, but require Perl 5.8.x+. For example:

prefork mpm での alarm() について話をすると, PSIX シグナルでは機能しているように見えますが, Perl 5.8.x+ を必要とします。例えば:

use POSIX qw(SIGALRM);
my $mask = POSIX::SigSet->new( SIGALRM );
my $action = POSIX::SigAction->new(sub { die "alarm" }, $mask);
my $oldaction = POSIX::SigAction->new();
POSIX::sigaction(SIGALRM, $action, $oldaction );
eval {
alarm 2;
sleep 10 # some real code should be here
alarm 0;
};
POSIX::sigaction(SIGALRM, $oldaction); # restore original
warn "got alarm" if $@ and $@ =~ /alarm/;

For more details see: http://search.cpan.org/dist/perl/ext/POSIX/POSIX.pod#POSIX::SigAction.
One could use the $SIG{ALRM} technique, working for 5.6.x+, but it works only under DSO modperl build. Moreover starting from 5.8.0 Perl delays signal delivery, making signals safe. This change may break previously working code. For more information please see: http://search.cpan.org/dist/perl/pod/perl58delta.pod#Safe_Signals and http://search.cpan.org/dist/perl/pod/perlipc.pod#Deferred_Signals_%28Safe_Signals%29.

5.6.x+ で機能する, $SIG{ALRM} テクニックを使えますが, それは DSO modperl ビルドでのみ機能します。そのうえ 5.8.0 以降 Perl はシグナルの配送を遅らせて, 安全なシグナルにします。この変更は以前機能していたコードを壊すかもしれません。詳細はこちらを参照してください: http://search.cpan.org/dist/perl/pod/perl58delta.pod#Safe_Signals と http://search.cpan.org/dist/perl/pod/perlipc.pod#Deferred_Signals_%28Safe_Signals%29。
For example if you had the alarm code:

例えばもしあなたが alarm のコードをもっていたなら:

eval {
local $SIG{ALRM} = sub { die "alarm" };
alarm 3;
sleep 10; # in reality some real code should be here
alarm 0;
};
die "the operation was aborted" if $@ and $@ =~ /alarm/;

It may not work anymore. Starting from 5.8.1 it's possible to circumvent the safeness of signals, by setting:

これはもう機能しないかもしれません。5.8.1 以降はシグナルの安全性を出し抜くことができます, この設定で:

$ENV{PERL_SIGNALS} = "unsafe";

as soon as you start your program (e.g. in the case of mod_perl in startup.pl). As of this writing, this workaround fails on MacOSX, POSIX signals must be used instead.

あなたがあなたのプログラムをスタートした直後で (e.g. mod_perl のケースでは startup.pl で)。これを書いている時点で, この回避策は MacOSX で失敗します, かわりに POSIX シグナルを使う必要がります。

For more information please refer to: http://search.cpan.org/dist/perl/pod/perl581delta.pod#Unsafe_signals_again_available and http://search.cpan.org/dist/perl/pod/perlrun.pod#PERL_SIGNALS.
Though if you use perl 5.8.x+ it's preferrable to use the POSIX API technique explained earlier in this section.

とはいえあなたが 5.8.x+ を使うならこのセクションで前述した POSIX API テクニックを使うことが望ましいです。


mod_perl 環境での Perl の仕様 : Perl Specifics in the mod_perl Environment


In the following sections we discuss the specifics of Perl behavior under mod_perl.

次のセクションで私たちは mod_perl のもとでの Perl の仕様の詳細を論じます。


BEGIN ブロック : BEGIN Blocks


Perl executes BEGIN blocks as soon as possible, at the time of compiling the code. The same is true under mod_perl. However, since mod_perl normally only compiles scripts and modules once, either in the parent server (at the server startup) or once per-child (on the first request using a module), BEGIN blocks in that code will only be run once. As the perlmod manpage explains, once a BEGIN block has run, it is immediately undefined. In the mod_perl environment, this means that BEGIN blocks will not be run during the response to an incoming request unless that request happens to be the one that causes the compilation of the code, i.e. if it wasn't loaded yet.

Perl はコードのコンパイルタイムで, BEGIN ブロックをできるだけ速やかに実行します。mod_perl のもとでも同じです。しかし, 普通 mod_perl はスクリプトとモジュールを各 parent サーバで 1 度 (サーバのスタートアップ) のみ, または child ごと (モジュールを使う最初のリクエスト) に 1 度コンパイルするので, そのコードの BEGIN ブロックは 1 度だけ実行されます。perlmod man ページで説明しているように, BEGIN ブロックが実行されると, それはすぐに未定義になります。mod_perl 環境で, これは BEGIN ブロックがそのリクエストがコードのコンパイルを発生させるものでない i.e. それがまだロードされていない限り, インカミングのリクエストへのレスポンスの間では走らないことを意味します。
BEGIN blocks in modules and files pulled in via require() or use() will be executed:

モジュールとファイルの中で require() または use() を介して取り出された BEGIN ブロックは実行されます:

  • Only once, if pulled in by the parent process at the server startup.

    1 度のみ, サーバスタートアップで parent プロセスによってプルされた場合。

  • Once per each child process or Perl interpreter if not pulled in by the parent process.

    各 child プロセスまたは Perl インタプリタごとに 1 度, parent プロセスによってプルされていない場合。

  • An additional time, once per each child process or Perl interpreter if the module is reloaded off disk again via Apache2::Reload.

    追加時間, モジュールが Apache2::Reload を介してモジュールが再度リロードされる場合に各 child プロセスまたは Perl インタプリタごとに 1 度

  • Unpredictable if you fiddle with %INC yourself.

    あなたがあなた自身で %INC をいじくると予測不能。


The BEGIN blocks behavior is different in ModPerl::Registry and ModPerl::PerlRun handlers, and their subclasses.

BEGIN ブロックの振る舞いは ModPerl::Registry と ModPerl::PerlRun ハンドラ, それからそれらのサブクラスで異なります。


CHECK と INIT ブロック : CHECK and INIT Block


CHECK and INIT blocks run when the source code compilation is complete, but before the program starts. CHECK can mean "checkpoint" or "double-check" or even just "stop". INIT stands for "initialization". The difference is subtle; CHECK blocks are run just after the compilation ends, INIT just before the runtime begins. (Hence the -c command-line perl option runs CHECK blocks but not INIT blocks.)

CHECK と INIT ブロックはソースコードのコンパイルが完了したが, プログラムがスタートする前に走ります。CHECK は "チェックポイント" や "ダブルチェック" あるいは単に "ストップ" の意味にできます。INIT は "initialization (# 初期化)" の略語です。その違いはわずかです; CHECK ブロックはコンパイルが終了した直後に走り, INIT はランタイムが始まる直前です。(したがってコマンドラインの perl オプション -c は CHECK ブロックは実行しますが INIT ブロックはそうではありません。)
Perl only calls these blocks during perl_parse(), which mod_perl calls once at startup time. Under threaded mpm, these blocks will be called once per parent perl interpreter startup. Therefore CHECK and INIT blocks don't work after the server is started, for the same reason these code samples don't work:

Perl は perl_parse() の間でのみこれらのブロックを呼びます, mod_perl はこれをスタートアップタイムで 1 度呼びます。スレッド mpm のもとで, これらのブロックは parent の perl インタプリタのスタートアップ毎に 1 度呼ばれます。したがって CHECK と INIT ブロックはサーバがスタートした後では機能しません, 同じ理由でこれらのコードサンプルは機能しません:

% perl -e 'eval qq(CHECK { print "ok\n" })'
% perl -e 'eval qq(INIT { print "ok\n" })'



END ブロック : END Blocks


As the perlmod manpage explains, an END block is executed as late as possible, that is, when the interpreter exits. So for example mod_cgi will run its END blocks on each invocation, since on every invocation it starts a new interpreter and then kills it when the request processing is done.

perlmod man ページが説明しているように, END ブロックはできるだけ遅く実行されます, つまり, インタプリタが終了するときです。ですから例えば mod_cgi はこの END ブロックを呼び出しごとに実行します, すべての呼び出しで新しいインタプリタがスタートするためでそのリクエストの処理が完了した時にはそれをキルします。
In the mod_perl environment, the interpreter does not exit after serving a single request (unless it is configured to do so) and hence it will run its END blocks only when it exits, which usually happens during the server shutdown, but may also happen earlier than that (e.g. a process exits because it has served a MaxRequestsPerChild number of requests).

mod_perl 環境では, 単一のリクエストをサーブしたあとでインタプリタを終了しない (それがそうするように構成されていない限り) ためその END ブロックはそれが終了した時のみ実行し, これは通常サーバがシャットダウンの間で発生しますが, その前にも発生することもあります (e.g. MaxRequestsPerChild の数だけリクエストがサーブされたためプロセスが終了する)。
mod_perl does make a special case for scripts running under ModPerl::Registry and friends.

The Cleaning up section explains how to deal with cleanups for non-Registry handlers.

ModPerl::Global API: special_list_register, special_list_call and special_list_clear, internally used by registry handlers, can be used to run END blocks at arbitrary times.

mod_perl は ModPerl::Registry とその仲間のもとで実行するスクリプトのための特別なケースを作ります。

Cleaning up セクションは非レジストリハンドルのクリーンアップをどのように扱うを説明します。

ModPerl::Global API: レジストリハンドラにより内部的に使われる, special_list_register, special_list_call それから special_list_clear は, END ブロックを任意のタイミングで実行するために使えます。


リクエストローカライズされたグローバル : Request-localized Globals


mod_perl 2.0 provides two types of SetHandler handlers: modperl and perl-script. Remember that the SetHandler directive is only relevant for the response phase handlers, it neither needed nor affects non-response phases.

Under the handler:

mod_perl 2.0 は 2 つのタイプの SetHandler ハンドラを提供します: modperl と perl-script です。SetHandler ディレクティブはレスポンスフェーズのハンドラにのみ関連し, それは非レスポンスフェーズでは不要で影響も与えないことを覚えておいてください。

このハンドラのもとでは:

SetHandler perl-script

several special global Perl variables are saved before the handler is called and restored afterwards. This includes: %ENV, @INC, $/, STDOUT's $| and END blocks array (PL_endav).

Under:

いくつかの特別でグローバルな Perl 変数はハンドラが呼ばれる前に保存されてその後に復元されます。これは含みます: %ENV, @INC, $/, STDOUT の $| と END ブロック配列 (PL_endav)。

これのもとでは:

SetHandler modperl

nothing is restored, so you should be especially careful to remember localize all special Perl variables so the local changes won't affect other handlers.

何も復元されません, ですからあなたはローカルの変更が他のハンドラに影響しないようにローカライズしたすべての特別な Perl 変数を特に注意して覚えておかなければなりません。


exit


In the normal Perl code exit() is used to stop the program flow and exit the Perl interpreter. However under mod_perl we only want the stop the program flow without killing the Perl interpreter.

普通の Perl コードでの exit() はプログラムの流れの停止と Perl インタプリタの終了のために使われます。しかしながら mod_perl のもとでは私たちは Perl インタプリタをキルすることを除いてプログラムの流れを停止のみをします。
You should take no action if your code includes exit() calls and it's OK to continue using them. mod_perl worries to override the exit() function with its own version which stops the program flow, and performs all the necessary cleanups, but doesn't kill the server. This is done by overriding:

あなたのコードが exit() コールを含んでいてそれを継続して使っても OK な場合あなたは何もしない方がよいです。mod_perl は exit() ファンクションがプログラムの流れを停止し, すべての必要なクリーアップを実行するが, サーバをキルしない独自のバージョンで上書きされることを心配しています。これは次のオーバライドによって行われます:

*CORE::GLOBAL::exit = \&ModPerl::Util::exit;

so if you mess up with *CORE::GLOBAL::exit yourself you better know what you are doing.

You can still call CORE::exit to kill the interpreter, again if you know what you are doing.

One caveat is when exit is called inside eval -- the ModPerl::Util::exit documentation explains how to deal with this situation.

ですからもしなたが *CORE::GLOBAL::exit をあなた自身でごちゃ混ぜにするならあなたはあなたが何をしているか知っておいたほうがよいです。

あなたはまだインタプリタをキルするために CORE::exit を呼ぶことができます, あなたが何をしているかあなたが知っているならね。

ひとつの注意は exit が eval の内側で呼ばれるときです -- ModPerl::Util::exit ドキュメントはこの状況にどのように対応するかを説明しています。


ModPerl::Registry Handlers Family




舞台裏を見る : A Look Behind the Scenes


If you have a CGI script test.pl:

あなたが CGI スクリプト test.pl をもっているとして:

#!/usr/bin/perl
print "Content-type: text/plain\n\n";
print "Hello";

a typical registry family handler turns it into something like:

典型的なレジストリファミリのハンドラはこれをこのように変更します:

package foo_bar_baz;
sub handler {
local $0 = "/full/path/to/test.pl";
#line 1 test.pl
#!/usr/bin/perl
print "Content-type: text/plain\n\n";
print "Hello";
}

Turning it into an almost full-fledged mod_perl handler. The only difference is that it handles the return status for you. (META: more details on return status needed.)

It then executes it as:

それをほぼ一人前の mod_perl ハンドラに変更します。唯一の違いはあなたのための return ステータスを処理することです。(META: return ステータスの詳細が必要とされる。)

これは次のように実行します:

foo_bar_baz::handler($r);

passing the $r object as the only argument to the handler() function.

Depending on the used registry handler the package is made of the file path, the uri or anything else. Check the handler's documentation to learn which method is used.

handler() ファンクションへの唯一の引数として $r オブジェクトを渡しています。

使っているレジストリハンドラに応じてパッケージはファイルパス, uri やその他のもので成り立っています。どの手法が使われているを学ぶために the handler のドキュメントをチェックしてください。


$r オブジェクトをゲットする : Getting the $r Object


As explained in A Look Behind the Scenes the $r object is always passed to the registry script's special function handler as the first and the only argument, so you can get this object by accessing @_, since:

A Look Behind the Scenes で説明されているように $r オブジェクトはレジストリスクリプトの特別なファンクション handler に最初で唯一の引数として, 常に渡されるので, あなたは @_ にアクセスすることでこのオブジェクトをゲットできます, ですから:

my $r = shift;
print "Content-type: text/plain\n\n";
print "Hello";

is turned into:

これは次のように変わります:

sub handler {
my $r = shift;
print "Content-type: text/plain\n\n";
print "Hello";
}

behind the scenes. Now you can use $r to call various mod_perl methods, e.g. rewriting the script as:

舞台裏。いまのあなたはさまざまな mod_perl メソッドを呼ぶために $r を使えます, e.g. このようにスクリプトをリライトします:

my $r = shift;
$r->content_type('text/plain');
$r->print();

If you are deep inside some code and can't get to the entry point to reach for $r, you can use Apache2->request.

もしあなたがコードの奥深くで $r にリーチするためのエントリポイントを得ることができない場合, あなたは Apache2->request を使えます。


mod_perl でのスレッドコーティングの問題 : Threads Coding Issues Under mod_perl


The following sections discuss threading issues when running mod_perl under a threaded MPM.

次のセクションでスレッド化された MPM のもとで mod_perl を実行するときのスレッディングの問題を論じます。


スレッド環境の問題 : Thread-environment Issues


The "only" thing you have to worry about your code is that it's thread-safe and that you don't use functions that affect all threads in the same process.

あなたのコードについて "唯一" あなたが心配しなければならないことはそれがスレッドセーフでありあなたが同じプロセスのすべてのスレッドに影響するファンクションを使わないことです。
Perl 5.8.0 itself is thread-safe. That means that operations like push(), map(), chomp(), =, /, +=, etc. are thread-safe. Operations that involve system calls, may or may not be thread-safe. It all depends on whether the underlying C libraries used by the perl functions are thread-safe.

Perl 5.8.0 自体はスレッドセーフです。それは push(), map(), chomp(), =, /, +=, etc. のようなオペレーションがスレッドセーフであることを意味します。システムコールを伴うオペレーションは, スレッドセーフかもしれませんしそうでないかもしれません。それはすべて perl ファンクションによって使われる下部の C ライブラリがスレッドセーフかどうかに依存します。
For example the function localtime() is not thread-safe when the implementation of asctime(3) is not thread-safe. Other usually problematic functions include readdir(), srand(), etc.

例えばファンクション localtime() は asctime(3) の実装がスレッドセーフでなければスレッドセーフではありません。通常他で問題のあるファンクションは readdir(), srand(), etc を含みます。
Another important issue that shouldn't be missed is what some people refer to as thread-locality. Certain functions executed in a single thread affect the whole process and therefore all other threads running inside that process. For example if you chdir() in one thread, all other thread now see the current working directory of that thread that chdir()'ed to that directory. Other functions with similar effects include umask(), chroot(), etc. Currently there is no cure for this problem. You have to find these functions in your code and replace them with alternative solutions which don't incur this problem.

見逃してはならない他の重要な問題は一部の人々によりスレッドの局所性 (turead-locality) として参照するものです。シングルスレッドで実行される特定のファンクションはプロセス全体したがってそのプロセスの内部で走っているすべての他のスレッドに影響をあたえます。例えばあなたがひとつのスレッドで chdir() すると, そこで他のすべてのスレッドはそのスレッドが chdir() したディレクトリを現在のワーキングディレクトリだと見ます。似た効果の他のファンクションは umask(), chroot(), etc. を含みます。現在この問題の解決策はありません。あなたはこれらのファンクションをあなたのコードで見つけそれらをこの問題をともなわない代替のソリューションでリプレイスしなければなりません。
For more information refer to the perlthrtut (http://perldoc.perl.org/perlthrtut.html) manpage.

詳細は perlthrtut (http://perldoc.perl.org/perlthrtut.html) man ページを参照してください。


スレッドをデプロイする : Deploying Threads


This is actually quite unrelated to mod_perl 2.0. You don't have to know much about Perl threads, other than Thread-environment Issues, to have your code properly work under threaded MPM mod_perl.

これは実際には mod_perl 2.0 にまったく関係ありません。あなたはあなたのコードを MPM mod_perl のもとで適切に機能させるために, スレッド環境の問題ではない Perl のスレッドについて多くを知る必要はありません。
If you want to spawn your own threads, first of all study how the new ithreads Perl model works, by reading the perlthrtut, threads (http://search.cpan.org/search?query=threads) and threads::shared (http://search.cpan.org/search?query=threads%3A%3Ashared) manpages.

あなたがあなた独自のスレッドを生成する場合, まず最初に perlthrtut, threads (http://search.cpan.org/search?query=threads) と threads::shared (http://search.cpan.org/search?query=threads%3A%3Ashared) man ページを読むことで, どのように新しい ithreads Perl モデルが機能するかを学習します。
Artur Bergman wrote an article which explains how to port pure Perl modules to work properly with Perl ithreads. Issues with chdir() and other functions that rely on shared process' datastructures are discussed. http://www.perl.com/lpt/a/2002/06/11/threads.html.

Artur Bergman はPerl ithreads で適切に機能するためにピュア Perl モジュールをどのように移植するかを説明する記事を書きました。 chdir() の問題と共有プロセスのデータ構造に頼る他のファンクションが論じられています。http://www.perl.com/lpt/a/2002/06/11/threads.html


共有変数 : Shared Variables


Global variables are only global to the interpreter in which they are created. Other interpreters from other threads can't access that variable. Though it's possible to make existing variables shared between several threads running in the same process by using the function threads::shared::share(). New variables can be shared by using the shared attribute when creating them. This feature is documented in the threads::shared (http://search.cpan.org/search?query=threads%3A%3Ashared) manpage.

グローバル変数はそれが生成されたインタプリタでのみグローバルです。他のスレッドからの他のインタプリタはその変数にはアクセスできません。しかしながらファンクション threads::shared::share() を使うことで同じプロセスで走っているいくつかのスレッド間で既存の変数を共有させることは可能です。新しい変数はそれを生成するときに shared アトリビュートを使うことで共有させることができます。この機能は threads::shared (http://search.cpan.org/search?query=threads%3A%3Ashared) man ページでドキュメント化されています。


メンテナ : Maintainers



Maintainer is the person(s) you should contact with updates, corrections and patches.



作者 : Authors




Only the major authors are listed above. For contributors see the Changes file.


NEXT



次回は、「 Cooking Recipes 」を「 mod_perl 」公式サイト (https://perl.apache.org/index.html) より確認します。


参考情報は書籍「 続・初めての Perl 改訂版 」, 「 Effective Perl 第 2 版 」を中心に perldoc, Wikipedia および各 Web サイト。それと詳しい先輩。

目次 - Perl Index






















同じカテゴリー(Perl)の記事
 Perl mp2 翻訳 Web コンテンツ圧縮の FAQ (d228) (2023-10-11 23:49)
 Perl mp2 翻訳 既知のブラウザのバグの回避策をいくつか (d227) (2023-05-26 15:41)
 Perl mp2 翻訳 Perl と Apache でのキュートなトリック (d226) (2023-05-19 17:05)
 Perl mp2 翻訳 テンプレートシステムの選択 (d225) (2022-08-15 22:23)
 Perl mp2 翻訳 大規模 E コマースサイトの構築 (d224) (2022-06-15 20:43)
 Perl mp2 翻訳 チュートリアル (d223) (2022-06-15 20:42)
上の画像に書かれている文字を入力して下さい
 
<ご注意>
書き込まれた内容は公開され、ブログの持ち主だけが削除できます。

Llama
リャマ
TI-DA
てぃーだブログ
プロフィール
セラ (perlackline)
セラ (perlackline)
QRコード
QRCODE
オーナーへメッセージ

PAGE TOP ▲