Perl で書いた HTTP daemon 形式のシステムがあるのだが、Windows ユーザにとってはコマンド プロンプトからコマンドラインオプションを指定しての起動は繁雑でよろしくないらしい。
以前から管理用のGUIをつけようと思っていたのだが、現在の daemon プログラムにGUIをつけるとするとマルチスレッド化にしなければならないとか、そういう頭があって後まわしにしていた。
今回、まずはランチャと daemon のログモニタというレベルでGUIを作ってみることにした。 wxPerl でランチャを作ってそこから子プロセスとして daemon を起動するという形式。 ランチャ側のアイドルループで、daemon の標準出力・標準エラー出力を読み出して表示するというもの。Linux 上ではうまく動いた。
といった感じ。
リャマ本を使用した社内 Perl 勉強会の13回目を開催。今日は6人。
今日は「初めてのPerl 第3版」第14章「プロセス管理」が範囲。
Perl が glue としての真価を発揮できる章である。
system、exec、パイプオープン、`...`、標準エラー出力のリダイレクト(2>)、STDOUT/STDERR の再オープンなど出席者によって回答がバラけて、今回ははからずも効果的であった (問題がらさすがに fork はいなかった)。
Windows では回答しづらい課題かと思っていたが、思ったより問題なく実行できていたようである。
Windows 上の date コマンドで、曜日を表示させる方法について1人だけ気がついた人がいて他の人が悔しがっていた。
make test で実行するテストスクリプトの中で、標準エラー出力を止めたい場合がある (わざとエラーを起こす時など)。
Perl 5.8.8 の ExtUtils/MM_Unix.pm を参考に
{ local *STDERR_COPY; my $duped = 0; $duped = 1 if open(STDERR_COPY, '>&STDERR'); open(STDERR, '> ' . File::Spec->devnull()) if $duped; my $result = `$command`; my $status = $?; open(STDERR, '>&STDERR_COPY') if $duped; } warn "This message is printed to STDERR\n";
としてみた。 Linux と Win32 ではとりあえずうまくいって動いている。
(open が2引数なのは、当時古い Perl バージョンでも動くように書いたから)
Visual C++ 2005 で開発のプログラムがどうもメモリリークしているっぽい。 メモリリーク検出を仕込む方法のメモ。
デバッグバージョンのヒープ割り当て関数を使うようにするマクロ定義と crtdbg.h のインクルードをする。 メモリリーク情報ダンプの際にレポートにファイル名と行番号が出るように new を書き換えるマクロを定義する。
// デバッグバージョンのヒープ割り当て関数を使うようにする。 #ifdef _DEBUG #define _CRTDBG_MAP_ALLOC #include <stdlib.h> #include <crtdbg.h> #endif // _CRTDBG_MAP_ALLOC に関係なくプリコンパイルしたいもの。 // かつ new を書き換えるとコンパイルが通らなくなるヘッダファイル群。 #include <string> #ifdef _DEBUG // プリコンパイルするほどではないけど、 // new を書き換えるとコンパイルが通らなくなるヘッダファイル群。 // 例えば。 #include <map> #define new new(_NORMAL_BLOCK, __FILE__, __LINE__) #endif // プリコンパイルしていもの。 #include <myproj/utility.h>
終了時にメモリリーク情報をダンプさせるようにする。 また、コンソールアプリケーションの標準エラー出力にレポートが出力されるように設定する。
int main(int argc, char* argv[]) { // 終了時にメモリリーク情報をダンプさせる。 _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); // レポートをファイルに書き出させる。 _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE); _CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE); // レポートを標準エラー出力に出力させる。 _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR); _CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDERR); _CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDERR); // 処理を開始。 ... }
意図的に出していて問題のない標準エラー出力への警告などをテスト実行(prove)時には出さないようにしたいというのはままある。で話題になった時にずいぶん昔にやった方法を紹介したりするのだけれど、まあ毎回自前で dup するのもということで CPAN モジュール探した。
期待する標準エラー出力への出力かどうかのテストをするなら Test:: 系をだけれど、ここでは単純に抑制したいだけなので Capture::Tiny で良いかな。
なお標準エラー出力をまるっと止めると、出ることが意図されていない警告にも気がつかなくなるので注意を。
#!/usr/bin/perl use warnings; use strict; use Test::More; use Capture::Tiny qw/capture_stderr/; sub warn_function { warn "WARN FUNCTION"; return 1; } sub warn_command { `echo "WARN COMMAND" >&2`; return 1; } sub uuv_function { my $undef_var; # Use of uninitialized value return $undef_var ne "dog"; } subtest capture_stderr => sub { capture_stderr sub { ok warn_function; }; capture_stderr sub { ok warn_command; }; capture_stderr sub { ok uuv_function; }; }; done_testing;
Naney (なにい) です。株式会社MIXIで SNS 事業の部長をしています。
※本サイトの内容は個人的見解であり所属組織とは関係ありません。