- PR -

Runtime#exec() のプロセスを一定時間で破棄したい

1
投稿者投稿内容
Asato
会議室デビュー日: 2006/10/28
投稿数: 10
投稿日時: 2006-10-28 13:44
こんにちは。
RedHat EL4の環境で外部プロセスを実行させているのですが、
時々そのプロセスが無限ループに陥ってしまうため、
一定時間後にそのプロセスを破棄するプログラムを考えました。

外部プロセスはffmpegで、スレッドで実行し、TimerTaskが一定時間後に
ffmpegのスレッドのプロセスを破棄するという内容なのですが、
どうも時間が経過してもTimerTaskのrun()が起動していないようです。
まずい点があればご教授ください。

また、interruptした後、すぐにfinalizerを明示的に呼び出す必要もあるのでしょうか?

====メイン=====

Thread th = new Thread(new ffmpegRunnable(cmd_d));

// タイマー設定
Timer timer=new Timer(true);
TimerTask dTask=new MyTimerTask(th);

th.run();
timer.schedule(dTask, 10000); //10秒後に対象のスレッドを停止

==========================================
class MyTimerTask extends TimerTask {
Thread th;
ffmpegRunnable runnable = null;

public MyTimerTask(Thread th) {
super();
this.th=th;
}

public void run() {
if(th.isAlive()){
th.interrupt();
th = null;
}
}
}
==========================================
private class ffmpegRunnable implements Runnable{
String[] cmd = null;
Process process = null;

ffmpegRunnable(String[] str){
cmd = str;
}

protected void finalize(){
if(process != null){
System.out.println("finalize");
process.destroy();
process = null;
}
}

public void run() {
try {
// 外部呼出しプロセス実行
process = Runtime.getRuntime().exec(cmd);

InputStream stdIn = process.getInputStream();
InputStream errIn = process.getErrorStream();
BufferedReader brStd = new BufferedReader(
                     new InputStreamReader(stdIn));
BufferedReader brErr = new BufferedReader(
new InputStreamReader(errIn));
// ログをとるためのファイル出力ストリーム
FileOutputStream fos = new FileOutputStream(LOGFILE, true);
BufferedWriter cmdlog = new BufferedWriter(
new OutputStreamWriter(fos));

String lineStd;
String lineErr;
while ((lineStd = brStd.readLine()) != null) {
logger.fine(lineStd);
}
while ((lineErr = brErr.readLine()) != null) {
// コマンド実行結果をファイルに保存する
cmdlog.write(lineErr);
cmdlog.newLine();
}
cmdlog.newLine();

int ret = process.waitFor();
cmdlog.flush();
cmdlog.close();

stdIn.close();
brStd.close();
fos.close();
errIn.close();
brErr.close();

} catch (IOException e) {
// exec()で例外が発生 または、Streamで例外発生
e.printStackTrace();
logger.info(e.toString());
} catch (InterruptedException e) {
// waitFor()で例外が発生
e.printStackTrace();
logger.info(e.toString());
} finally{
process.destroy();
}
}
}
大ベテラン
会議室デビュー日: 2006/06/28
投稿数: 116
投稿日時: 2006-10-28 15:28
「メイン」部で、変数thに
・何を設定しているか
・何をしようとしているか
を追ってみてください。

引用:
また、interruptした後、すぐにfinalizerを明示的に呼び出す必要もあるのでしょうか?


これは特に必要ないと思います。
(もし必要ということであればinterruptされなかった場合でも明示的に呼び出さなければならないということになりますよね?)
ただし、提示のためにソースを簡略化しているのならば良いですが、ストリームの操作後は
finally句でもcloseを記述しておくべきです。
Asato
会議室デビュー日: 2006/10/28
投稿数: 10
投稿日時: 2006-10-28 17:08
ありがとうございます。

取り急ぎ、interruptは呼び出せました。
th.run()ではなく、th.start()でしたね。。。
確かに動いていたけどマルチスレッドではなかったような・・・(^^

その代わり、以下の例外が発生してしまいました。
現在調査中ですが、一応乗せておきます。

java.io.IOException: Bad file descriptor
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:191)
at sun.nio.cs.StreamDecoder$CharsetSD.readBytes(StreamDecoder.java:408)
at sun.nio.cs.StreamDecoder$CharsetSD.implRead(StreamDecoder.java:448)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:182)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at conv.MovConvert$ffmpegRunnable.run(MovConvert.java:520)
at java.lang.Thread.run(Thread.java:536)
Oct 28, 2006 4:41:04 PM conv.MovConvert$ffmpegRunnable run
INFO: java.io.IOException: Bad file descriptor
java.lang.NullPointerException
at conv.MovConvert$ffmpegRunnable.run(MovConvert.java:548)
at java.lang.Thread.run(Thread.java:536)
java.io.IOException: Bad file descriptor
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:191)
at sun.nio.cs.StreamDecoder$CharsetSD.readBytes(StreamDecoder.java:408)
at sun.nio.cs.StreamDecoder$CharsetSD.implRead(StreamDecoder.java:448)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:182)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at conv.MovConvert$ffmpegRunnable.run(MovConvert.java:520)
at java.lang.Thread.run(Thread.java:536)
Oct 28, 2006 4:41:04 PM conv.MovConvert$ffmpegRunnable run
INFO: java.io.IOException: Bad file descriptor
java.lang.NullPointerException
at conv.MovConvert$ffmpegRunnable.run(MovConvert.java:548)
at java.lang.Thread.run(Thread.java:536)
java.io.IOException: Bad file descriptor
at java.io.FileInputStream.readBytes(Native Method)
at java.io.FileInputStream.read(FileInputStream.java:191)
at sun.nio.cs.StreamDecoder$CharsetSD.readBytes(StreamDecoder.java:408)
at sun.nio.cs.StreamDecoder$CharsetSD.implRead(StreamDecoder.java:448)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:182)
at java.io.InputStreamReader.read(InputStreamReader.java:167)
at java.io.BufferedReader.fill(BufferedReader.java:136)
at java.io.BufferedReader.readLine(BufferedReader.java:299)
at java.io.BufferedReader.readLine(BufferedReader.java:362)
at conv.MovConvert$ffmpegRunnable.run(MovConvert.java:520)
at java.lang.Thread.run(Thread.java:536)
Oct 28, 2006 4:41:04 PM conv.MovConvert$ffmpegRunnable run
INFO: java.io.IOException: Bad file descriptor
java.lang.NullPointerException
at conv.MovConvert$ffmpegRunnable.run(MovConvert.java:548)
at java.lang.Thread.run(Thread.java:536)
Asato
会議室デビュー日: 2006/10/28
投稿数: 10
投稿日時: 2006-10-28 18:53
自己レスです。

試行錯誤の結果、うまく無限ループをとめることができたようです。
最終的に、waitFor()で待機している間に、interrupt()を呼んで
以下の例外が発生しました。(これは出てしまう例外ですよね)

java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:426)
at java.lang.UNIXProcess.waitFor(UNIXProcess.java:160)
at conv.MovConvert$ffmpegRunnable.run(MovConvert.java:519)
at java.lang.Thread.run(Thread.java:536)

どうもありがとうございました。
1

スキルアップ/キャリアアップ(JOB@IT)