ps とかで表示されるプロセス名をわかりやすくしたいという話です。
Starman だと $0 に適当な値を入れてくれて、master なのか worker なのかとか、どの psgi が動いているかとかがわかるのですが、Starlet ではそういうことをやってくれないので、1つのサーバで複数インスタンス動かしていると、plackup のプロセスだらけで、どれがどれだかわからなくなります。
app.psgi で $0 で設定すれば良いかと思ったが
app.psgi で $0 設定したらとりあえずいいだろ、と思ってやってみましたが、どうも上手くいきません。app.psgi 内で $0 を warn してみるとそもそも plackup になってもいません。
調べてみると、Plack::Util::load_psgi で使っている _load_sandbox 内で local $0 をしてから app.psgi を do しており、ロード後に元のプロセス名に戻ってしまうようです。
ということで、単純に app.psgi で $0 を書きかえても plackup を使っている場合書きかわりません
Starlet 用のハックを入れる
なんかうまい方法がなさそうなので以下のようなクソハックを app.psgi に入れました。
{
### set process name for Starlet
use Parallel::Prefork;
my $name = $0;
my $orig_new = \&Parallel::Prefork::new;
no warnings 'redefine';
*Parallel::Prefork::new = sub {
my ($class, $opts) = @_;
$opts->{before_fork} = sub {
$0 = "$name (worker)"
};
$opts->{after_fork} = sub {
$0 = "$name (master)"
};
$orig_new->($class, $opts);
};
};
Starlet は Parallel::Prefork を使っているので、前もって use して new を書きかえて before_fork / after_fork を設定します。
before_fork / after_fork は Parallel::Prefork の機能でセットできるフックポイントですfork 前に worker プロセス用の $0 を設定して、fork 後に $0 を master 用の値に変えています。なのでタイミングによっては master プロセスも一瞬 worker 表示になります。
app.psgi ロード時のコンテキストでは $0 には .psgi のファイル名が入っています。これは上記の Plack::Util::_load_sandbox で設定されたものです。ということで、ロード時のコンテキストの$0を保存しておいて、後の $0 の設定に使っています。
app.psgi が Starlet 専用みたいになってキモいですが、Parallel::Prefork をロードする以上の害はとりあえずないのと、自分の場合は開発中に Standalone で動かす以外は Starlet を使うことにしているので問題ありません。
これで以下のようになりました。
cho45 4699 0.0 0.5 185432 5332 ? S May11 0:00 /home/cho45/project/COQSO/script/app.psgi (master) cho45 4700 0.0 2.4 296604 25168 ? S May11 0:09 /home/cho45/project/COQSO/script/app.psgi (worker) cho45 4701 0.0 2.5 296820 26468 ? S May11 0:11 /home/cho45/project/COQSO/script/app.psgi (worker) cho45 4702 0.0 1.8 302304 19136 ? S May11 0:11 /home/cho45/project/COQSO/script/app.psgi (worker)