スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

外部プログラム実行のタイムアウト処理(Ruby)

数か月放置し続けた問題


次のような動作をするプログラムを考えます。
  1. 時間のかかりそうな外部プログラムを実行する。
  2. 外部プログラムが終了したら、外部プログラムの標準出力を拾って、それを表示する。
  3. 2秒以内に終わらなかったら、外部プログラムをKILLする。

簡単そうですね?

実行環境はwindowsです。


時間かかりそうな外部プログラム


4秒間空のループを回し続けるのは嫌なので、%$\sqrt{2}$%を計算してもらいました。結果はoutputしませんが。
このプログラムを「sqrt2.rb」と名付けて保存します。

sqr = Rational(2,1)
low = Rational(1,1)
high = Rational(2,1)

begin_time = Time.now
while (Time.now - begin_time < 4)
c = (low + high) / 2
if c * c < sqr
low = c
else
high = c
end
end

result = (low + high) / 2

puts "finish"


素朴


timeoutとpopenを使えば簡単に書けそうですが・・・。

require 'timeout'
require 'benchmark'

total_time = Time.now

begin
pid = nil
com = nil
result = nil
tictoc = Benchmark.realtime{
Timeout.timeout(2) {
com = IO.popen("ruby sqrt2.rb")
pid = com.pid
result = com.read
}
}
puts result
puts "time #{tictoc}"
rescue Timeout::Error => err
puts "timeout"
Process.kill('SIGINT', pid)
com.close unless com.nil?
end

puts "total_time #{Time.now-total_time}"

実行結果
timeout
total_time 4.1634203

全体で4秒掛かってます。タイムアウトしてない!?

「puts "timeout"」を「puts "#{Time.now-total_time}"」に書き換えれば分かりますが、
外部プログラムが終わってからrescueに飛んでいます。意味ないです。


スレッドで対処する


timeoutメソッドは捨てて、別の方法を考えます。


2つのスレッドを作ります。
一方をタイムアウトスレッド、もう一方を実行スレッド、2つのスレッドの親玉をメインスレッドと呼びましょう。

2つのスレッドを実行させた後、メインスレッドは一旦寝ます。

タイムアウトスレッドは、2秒待ってから、メインスレッドを叩き起こす。
実行スレッドは、外部プログラムが終了したら、メインスレッドを叩き起こす。

たたき起こされたメインスレッドは、2つのスレッドを閉じて、必要ならば外部プログラムをkillする。


これでうまく行くみたいです。後述。




(2016/11/23追記)
実際に自分の個人プロジェクトに実装したところ、うまく行かない。

処理は確かに返ってくる。しかし肝心のProcessがうまくkill出来ていない。

tasklistコマンド等仕込んで原因を探ってみると、cmd.exeを作り、その子供としてruby.exeが呼ばれていた。
spawnで拾っていたプロセスIDはcmd.exeだった。cmd.exeをkillしてもruby.exeはkillしない。


Linuxの場合、プロセスグループを新たに作成して、プロセスグループごとKillすればよい。らしい。

参考:外部コマンドを実行してタイムアウトしたらkillする


windowsではプロセスグループという概念が無いので、同じように実装するとrubyがエラー吐く。

しかし、親子関係は存在するので実装は可能。子もまとめてKillするには、taskkillコマンドを使って、
system("taskkill /T /F /PID #{pid}")
と記述すればよい(ただし変数pidはspawnから得たプロセスID)。


ちょっときつい。
スポンサーサイト

テーマ : プログラミング
ジャンル : コンピュータ

tag : Ruby

コメントの投稿

非公開コメント

ブログ移転のお知らせ
ブログをshonen.hateblo.jpに移転します. 新規の記事はこちらに投稿します.
プロフィール

舞葉(ぶよう)

Author:舞葉(ぶよう)
github.io
はてなブログ(競プロ)

古い記事のソースコードは色分けしていないので、高機能テキストエディタに貼り付けたほうが見やすいかも。

検索フォーム
このブログについて
自分がつまづいた話題、なんとなく書きたいと思ったこと、ググったけど殆ど資料なかったぞオイ な話等をアップする予定。通りすがりでも、参考になっていただければと。プログラムの例外入力、メモリリークは責任負いません。投稿された記事は修正・削除する場合があります。
カテゴリ
タグ

HSP3アルゴリズムとデータ構造c++RubyJavaUnity画像解析C機械学習C#LinuxcodeIQKinectMinecraftTonyuSystemraspberrypiPythonHTML5音声制御Simulinkruby俺ルール通信制御Javascriptシミュレーション

counter-shinobi
固定記事
最新記事
最新コメント
月別アーカイブ
ブロとも申請フォーム

この人とブロともになる

アクセスランキング
[ジャンルランキング]
コンピュータ
635位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
94位
アクセスランキングを見る>>
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。