takayasu: July 2009 Archives

プログラムを書く際に処理をタイムアウトさせたい場合というのはよくあると思います。
そんなときに便利なのが、alarmです。
今回は、Perlプログラムでalarmを使ってタイムアウト処理を実装したいと思います。

alarmは対象の処理が指定した時間(秒)たっても終了しない場合、SIGALRMシグナルを発生させます。
例として、ユーザからの入力を30秒でタイムアウトさせるプログラムを書いてみます。

#!/usr/bin/perl

use strict;

# タイムアウトするまでの時間(秒数)
my $TIMEOUT = 30;

print "What your name??: ";
alarm($TIMEOUT);
my $name = ;
my $timeleft = alarm(0);
print "Hello! $name";


alarmで囲った部分、ユーザからの入力待つ部分がタイムアウト処理の対象になります。
ユーザが30秒以上入力しない場合、SIGALRMシグナルが発生しプログラムが終了します。
実際に30秒放置しておくと以下のような画面になります。

[hiroki@capybara]~% ./sig_alarm.pl
What your name??: zsh: alarm      ./sig_alarm.pl
[hiroki@capybara]~%

このままでもプログラムを終了させることはできるのですが、SIGALRM発生後に後処理を行いたいということが多いと思います。
# このプログラムでは特にこのままでも問題ないのですが...
上記のプログラムを改良しタイムアウトした際にメッセージを表示するようにしたいと思います。
evalとdieを組み合わせることで後処理を実装することができます。
下記が実装例です。

#!/usr/bin/perl

use strict;

my $TIMEOUT = 30;

print "What your name??: ";
my $name = '';
eval {
local $SIG{ALRM} = sub {die};
alarm($TIMEOUT);
$name = ;
my $timeleft = alarm(0);
};

if ($@) {
# タイムアウト
print "\nERROR: TIMEOUT\n";
}else{
# 正常終了
print "Hello! $name";
}


まず、タイムアウト処理をしたい対象をevalで囲んでdieしたときでもプログラム自体を終了しないようにします。
dieなどの割り込みが発生した場合には、$@にエラーメッセージが代入されるのでそれによって処理がタイムアウトしたかを判定しています。

eval内では、SIGALRMシグナルが発生したときでもプログラムが終了しないようにSIGALRMのシグナルハンドラを設定しています。
シグナルハンドラには関数のリファレンスを渡す必要があります。
上記例では、SIGALRMが発生した際にはdieするようにしています。
シグナルハンドラはlocalをつけて指定することで、スコープ内で発生した該当のシグナルだけつかまえることができます。
localを指定していない場合、プログラム全体の該当のシグナルハンドルを指定することになります。

上記のプログラムを実際にタイムアウトさせると下記のようになります。

[hiroki@capybara]~% ./sig_alarm.pl
What your name??:
ERROR: TIMEOUT
[hiroki@capybara]~%

今度はシェルからのメッセージではなく、きちんと自分自身のプログラムからのメッセージが表示されているのがわかると思います。


最後にalarmとsleepを併用することは推奨されません。
sleepがalarmを使って実装されていることが多く、正しく動かないことがあるからです。


alarmとevalとdieを組み合わせることでタイムアウトがないような処理にもタイムアウトが実装できるようになります。

最近めっきり飲料水系の記事を上げていませんでしたが、久しぶりに投稿します。
今回はオフィスの自販機に新たに加わっていたKIRIN COLAを飲んでみました。

さて、まず見た目ですが赤が目を引くデザインです。
自販機の多くは緑や青、黒といった缶が多いので意外と目立ちます。
缶には"コーラ好きのためのキリン初オリジナルコーラ"とあります。
確かに、キリンの炭酸飲料といえばキリンレモンのイメージがありますよね。
"キリン初"というところに私の期待は高まります。

さて、早速開けてみました。
香りはコカコーラより少し甘めな感じです。
ルートビアーのような強烈でインパクトのある香りではありません。

一口飲んでみました。
通常のコカコーラよりも甘めかつ炭酸も弱めです。
コーラの炭酸がちょっと強くて苦手...という方にはおススメです。

ちなみにこのKIRIN COLA、オフィスの自販機に入ったとたん大人気で、自販機はすでに売り切れでした。
暑くなるこれからの季節、最適な飲み物になりそうです。

KIRINCOLA.jpg

About this Archive

This page is a archive of recent entries written by takayasu in July 2009.

takayasu: April 2009 is the previous archive.

Find recent content on the main index or look in the archives to find all content.