java - про Process

stat5257402

у меня есть ворос про Process.
создал один Process так,
Process proc=null;
try{
proc = Runtime.getRuntime.exec("c:\\a.exe");
}catch(IOException e){}
вопрос состоит в том, что дописать программу чтобы выполнить следующие требования:
1)если время выполнения Process pro больше 5 минут, то остановить его и destroy
2)иначе время выполнения Process pro меньше 5 минут, надо выводить время выполнения.
спасибо.

danilov

Process proc=null;
try{
    proc = Runtime.getRuntime.exec("c:\\a.exe");
}catch(IOException e){}
Thread.sleep(5000 * 60);
try{
   int result = proc.exitValue;
   // пишем время
} catch(IllegalThreadStateException e) {
   proc.destroy;
   // пишем, что плохо
}
Как-то так... В любом случае, почитай http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Process.ht... - про exitValue особенно.

stat5257402

 

you wrote
Process proc=null;
try{
    proc = Runtime.getRuntime.exec("c:\\a.exe");
}catch(IOException e){}
Thread.sleep(5000 * 60);
try{
   int result = proc.exitValue;
   // пишем время
} catch(IllegalThreadStateException e) {
   proc.destroy;
   // пишем, что плохо
}

Как-то так... В любом случае, почитай http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Process.ht... - про exitValue особенно.
Так не правильно . Втаком случае текущий нить(current Thread) всегда ждёт 5 минут.
Если время выполнения pro только 2 секунды, тогда программа выводит 5 минут ? (не правильно)

stat5257402

подумаю, что надо использовать method wait(. но не знаю как правильно

danilov

Можно
boolean badExit = True;
while(не_прошло_5_мин){
try{
int result = proc.exitValue;
// пишем время
badExit = False;
break;
} catch(IllegalThreadStateException e) {}
}
if(badExit){
proc.destroy;
// нишем, что всё плохо
}

danilov

Проверил. Вот это работает:

import java.io.IOException;
public class Proc {
public static void main(String[] args) throws InterruptedException {
Process proc=null;
try{
proc = Runtime.getRuntime.exec("notepad");
}catch(IOException e){}
boolean badExit = true;
long maxTime = 1000000000;// 1 секунда
maxTime *= 300; // 5 минут
long startTime = System.nanoTime;
long curTime = System.nanoTime;
while(curTime - startTime < maxTime){
try{
int result = proc.exitValue;
System.err.println("Время " + (curTime - startTime) / 1000000 + " мсек");
badExit = false;
break;
} catch(IllegalThreadStateException e) {}
curTime = System.nanoTime;
}
if(badExit){
proc.destroy;
System.err.println("Всё плохо");
}
}
}

stat5257402

посмотрю

kokoc88

Зачем цикл?
 
public class ProcessTest
{
    public static void main(String args[])
    {
     try {
     Timer timer = new Timer(true);
     final Thread mainThread = Thread.currentThread;
     long timeBegin = System.currentTimeMillis;
     final Process process = Runtime.getRuntime.exec("calc.exe");
     timer.schedule(new TimerTask {
     public void run {
     mainThread.interrupt;
     process.destroy;
     }
     }, 5*60*1000);
     int result = process.waitFor;
     timer.cancel;
mainThread.interrupted;
     System.out.println("Process has exit with code " + result + " after " +
     (System.currentTimeMillis - timeBegin) + " milliseconds.");
     }
     catch (InterruptedException e) {
     System.out.println("Process didn't exit in 5 minutes.");
     }
     catch (Exception e) {
     System.out.println("Error.");
     }
    }
}

Marinavo_0507

Если процесс завершится сам чуть-чуть раньше таймера, то mainThread сможет начать уже что-то печатать про время, а тут таймер его прибьёт.
Race condition, однако.

kokoc88

Да, исправил.

Marinavo_0507

Ничё не исправил.
Например, waitfor уже сработал, а timer.cancel ещё нет, и тут оно как жахнет...

otets-mihail

Ну и выведется
"Process didn't exit in 5 minutes.", что не так далеко от истины.

Marinavo_0507

Может, выведется, а может, и не успеет, если TimerTask.run уже запущено оказалось - timer.cancel его не срубит.

Marinavo_0507

Я думаю, очевидно корректный метод примерно такой: создаётся два треда, один ждёт процесс, другой ждёт таймера.
Который первый дожидается, сигналит основному треду (хз, какие для этого средства в яве - нужен какой-нибудь message queue; можно сигналить через разделяемый объект, тогда дополнительное место для бага, если неосторожно сделать).
Основной тред получает сообщение, срубает оба треда.
Если успевает прийти два сообщения, то учитывать только первое.
Код написать не могу, могу только на C под POSIX попробовать аналог сделать.

otets-mihail

Ну если не успеет, выведется "Process has exit with code ..." что также можно считать правдой.

Marinavo_0507

Не так. Эта строчка может вывестись целиком, или вообще не до конца (атомарность System.out.println кто-нибудь обещает?).
А потом выведется "Process didn't exit in 5 minutes."

otets-mihail

Неа. System.out.println нельзя прервать interrupt'oм. Можно прервать только waitfor.

Marinavo_0507

> System.out.println нельзя прервать interrupt'oм.
А вдруг там внутри I/O через InterruptibleChannel?
Ну а если не прервёт, к чему тогда приведёт interrupt flag - тут моих знаний не хватает?

stat5257402

да, красивое решение.
есть другое без Timer ?

otets-mihail

Даже в списке исключений, кидаемых PrintStream.println(String x) нет InterruptedException.

Marinavo_0507

Ну всё равно interrupt flag останется у треда, на что он повлияет?

otets-mihail

При следующем вызове sleep/waitFor/... немедленно выкинет InterruptedException.

Marinavo_0507

ну значит, есть баг, так как в доке не написано, что этот код может нарушить работу след. вызова

Svyatogor

Можно и без Timer (но со второй нитью)

import java.io.IOException;
public class test {
static final String CALC = "c:\\winnt\\system32\\calc.exe";
static final long timeout = 5 * 60 * 1000;
static class ProcUtil implements Runnable {
boolean completed = true;
int retcode;
Process p;

ProcUtil(String pname) throws IOException {
p = Runtime.getRuntime.exec(pname);
}

public void run {
while (true) {
try {
retcode = p.waitFor;
completed = true;
return;
} catch (InterruptedException e) {}
}
}
void kill {
p.destroy;
}
}

public static void main(String [] args) {
ProcUtil p;
try {
p = new ProcUtil(CALC);
} catch (IOException bugs) {
bugs.printStackTrace;
return;
}
long ctime = System.currentTimeMillis;
long etime = ctime + timeout;
Thread ct = new Thread(p);
ct.start;
while (ctime < etime && ct.isAlive {
try {
ct.join(etime - ctime);
} catch (InterruptedException e) {
}
ctime = System.currentTimeMillis;
}
if (ct.isAlive {
p.kill;
System.err.println("Killed");
} else {
System.err.println("All OK");
}
}
}

По поводу цикла ожидания - не уверен, что нужен, но лишним не будет (тот же Object.wait(long millis) может прерываться "просто так")

aleks058

В .Net 2.0 будет примерно так:

Process newProcess = Process.Start("c:\\a.exe");
if (newProcess.WaitForExit(5 * 60 * 1000
Console.WriteLine("It took " + newProcess.TotalProcessorTime);
else
newProcess.Kill;

kokoc88

ну значит, есть баг, так как в доке не написано, что этот код может нарушить работу след. вызова
Ну вообще процесс прерывания потоков описан вполне детально. В данном случае всё будет нормально работать. Тут ведь речь идёт не об уничтожении потока, а именно о сигнале прерывания внутри java.
PS Я даже зря написал timer.cancel не подумав.

Marinavo_0507

> а именно о сигнале прерывания внутри java
у тебя этот сигнал останется по завершении фрагмента, и баг проявится
где-то далее по треду (что ещё хуже, чем если бы он проявился сразу)

kokoc88

у тебя этот сигнал останется по завершении фрагмента, и баг проявится
где-то далее по треду (что ещё хуже, чем если бы он проявился сразу)
У меня программа выйдет. Так что нигде баги не проявятся. Если тебе требуется пример фукнции, делающей всё тоже самое, я могу его написать.
Оставить комментарий
Имя или ник:
Комментарий: