hoomanv
asked on
The process does not terminate, nor does die
Hi experts
I have written a c program that generates a runtime error here is the code
char a[3];
a[5645456] = 0; // out-of-bounds array access
consider a.exe exploits this code to generate a runtime error.
Ok my problem is arising from this. In java I start a new process to execute a.exe in a single thread (named ExecutorThread) and another thread (named SimultaneousReader) to simultaneously read the output from the process’s inputstream. My ExecutorThread then calls process.waitFor() and waits till its finished. In main() I call executorThread.join(3000) to not wait more than 3 seconds for the process to be finished and after timeout a call to process.destroy() is made. As we expect that error occurs during the execution so windows will popup a message box telling you that “a.exe has encountered a problem and needs to be closed”, forcing you to press the button to terminate the process. So, if you don’t respond within 3 seconds, destroy method will be called to kill the process, although it fails to kill, but surprisingly the executorThread that was waiting since the call to process.waitFor() will resume, but the bad news is that the SimultaneousReader is still blocked waiting to read the next byte from inputstream. there is no way to interrupt it unless I ask it from OS. These two threads are used in software and there would be no man who interactively discards runtime errors that may occur during the job. So definitely I need a way to release the lock on SimultaneousReader and prepare it to accept new jobs (somewhat works like a thread pool). Any comment would be appreciated. If your solution is about non-blocking IO operations, please tell me exactly how to do it with traditional java.io.
I have written a c program that generates a runtime error here is the code
char a[3];
a[5645456] = 0; // out-of-bounds array access
consider a.exe exploits this code to generate a runtime error.
Ok my problem is arising from this. In java I start a new process to execute a.exe in a single thread (named ExecutorThread) and another thread (named SimultaneousReader) to simultaneously read the output from the process’s inputstream. My ExecutorThread then calls process.waitFor() and waits till its finished. In main() I call executorThread.join(3000) to not wait more than 3 seconds for the process to be finished and after timeout a call to process.destroy() is made. As we expect that error occurs during the execution so windows will popup a message box telling you that “a.exe has encountered a problem and needs to be closed”, forcing you to press the button to terminate the process. So, if you don’t respond within 3 seconds, destroy method will be called to kill the process, although it fails to kill, but surprisingly the executorThread that was waiting since the call to process.waitFor() will resume, but the bad news is that the SimultaneousReader is still blocked waiting to read the next byte from inputstream. there is no way to interrupt it unless I ask it from OS. These two threads are used in software and there would be no man who interactively discards runtime errors that may occur during the job. So definitely I need a way to release the lock on SimultaneousReader and prepare it to accept new jobs (somewhat works like a thread pool). Any comment would be appreciated. If your solution is about non-blocking IO operations, please tell me exactly how to do it with traditional java.io.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Try also closing the stream it is reading when you kill the process.
ASKER
CEHJ: I'm going to test it, wait ...
objects: inputstream.close() also blocks
objects: inputstream.close() also blocks
In case i wasn't clear, i meant use a concurrent class that will provide you with one, rather than constructing your own Thread
> objects: inputstream.close() also blocks
sounds like its blocked at the OS level
Try calling available() before doing a read() only call read() if there are bytes available. That way it won't block.
sounds like its blocked at the OS level
Try calling available() before doing a read() only call read() if there are bytes available. That way it won't block.
ASKER
unfortunatly InputStream.available() always returns 0; // javadoc says
CEHJ would you please write a sample code ? im not familiar with that package
CEHJ would you please write a sample code ? im not familiar with that package
> unfortunatly InputStream.available() always returns 0; // javadoc says
Thats for the base class :)
It returns the number of bytes available for reading, it wouldn't be much use if it always returned 0.
Thats for the base class :)
It returns the number of bytes available for reading, it wouldn't be much use if it always returned 0.
Nothing to it: all you do is call
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Executors.html#defaultThreadFactory()
http://java.sun.com/j2se/1.5.0/docs/api/java/util/concurrent/Executors.html#defaultThreadFactory()
ASKER
I also tested it on the Process's InputStream
thats all the thing that it does, always returns 0
I have seen the java source code for FileInputStream and I discoverd the available method is implemented at native level. so, does Process also implemente it too ? i think its a wreakness of this class
thats all the thing that it does, always returns 0
I have seen the java source code for FileInputStream and I discoverd the available method is implemented at native level. so, does Process also implemente it too ? i think its a wreakness of this class
>>Try calling available() before doing a read() only call read() if there are bytes available
That won't necessarily be that useful. In the case of a BufferedInputStream it won't really help you to continue reading the stream but effectively only tell you the number of bytes that have already been read
That won't necessarily be that useful. In the case of a BufferedInputStream it won't really help you to continue reading the stream but effectively only tell you the number of bytes that have already been read
>>In the case of a BufferedInputStream
(e.g.)
(e.g.)
You don't want to be using a buffered input stream, that would defaeaqt the purpose of what u are trying to achieve.
You should be using the output syttream of the process directly.
You should be using the output syttream of the process directly.
ASKER
wrapping the IS in a BufferedInputStream does not help neither. all it does is just calling the IS.available() and as I said before the Process's IS has not implemented available() to return correctly (I guess)
currently im reading the introduced java.util.concurrent to find something usefull (I also found that java 1.5 has a built in thread pooling support), but I think I have to rewrite my own thread to be able to use it in this way.
shortly SimulatanousReader is doing this:
run() {
while(running) {
is there any IS to read from ?
if no
wait until someone notifies me
read the entire input into buffer // this is the blocking line
do somthing
}
}
it seems i have to reimplement the entire class. i'll work on it but is it guaranteed 100% to solve the blocking issue ? is there any other way ? I just suggested that it may be solved by using non-blocking IO but I think the are other ways to overcome this
currently im reading the introduced java.util.concurrent to find something usefull (I also found that java 1.5 has a built in thread pooling support), but I think I have to rewrite my own thread to be able to use it in this way.
shortly SimulatanousReader is doing this:
run() {
while(running) {
is there any IS to read from ?
if no
wait until someone notifies me
read the entire input into buffer // this is the blocking line
do somthing
}
}
it seems i have to reimplement the entire class. i'll work on it but is it guaranteed 100% to solve the blocking issue ? is there any other way ? I just suggested that it may be solved by using non-blocking IO but I think the are other ways to overcome this
>>You don't want to be using a buffered input stream,
I wasn't suggesting one
>>it seems i have to reimplement the entire class.
Your class simply needs to implement Runnable
I wasn't suggesting one
>>it seems i have to reimplement the entire class.
Your class simply needs to implement Runnable
:-)
> and as I said before the Process's IS has not implemented available() to return correctly (I guess)
It does implement it correctly. Have used it many times to stop this exact problem :)
Just killing the the thread is going to still leave blocked resources.
It does implement it correctly. Have used it many times to stop this exact problem :)
Just killing the the thread is going to still leave blocked resources.
Did you get it going?
ASKER
hmm ?
What's the status?
ASKER
when windows takes control of the exe, even a call to available blocks. another way to overcome this is to use InterruptibleChannel but Process just gives me an inputstream not a channel. these two fails for me. you told me to use classes in java.util.concurrent but i dont have any idea on how to use them. im not clearly understand how these would help til I see an example. sorry I cant get the idea behind that
ASKER
another problem i have with process, when the a.exe is expected to do somthinf like this:
main() {
printf("hello"); // only 5 characters
while(true)
;
}
then the ExecutorThread waits for ever. if destroy the process and it successfully kills. BUT. if i call process.getExcitCode() i got an InterruptedThreadStateExce ption although the process is not running. and another severe problem: i cant access to the printed "hello" world from process. whu ? i found that if process prints more than 1024 byte the output is obtainable but in the case that I kill the process, output bytes less than 1024 would disapear. trying to call "cmd /c a.exe < in > out" can solve the issue but it brings another problem. process.destroy only kills the cmd and not the subprocess "a.exe".
main() {
printf("hello"); // only 5 characters
while(true)
;
}
then the ExecutorThread waits for ever. if destroy the process and it successfully kills. BUT. if i call process.getExcitCode() i got an InterruptedThreadStateExce
Why does main look like that? It doesn't exit
So why exactly did u accept the first comment?
ASKER
> Why does main look like that? It doesn't exit
some students have done their HWs and this app is engaged to run them. thus it must be prepared for encounter with such apps.
> So why exactly did u accept the first comment?
Honestly I was wrong
some students have done their HWs and this app is engaged to run them. thus it must be prepared for encounter with such apps.
> So why exactly did u accept the first comment?
Honestly I was wrong
then you should reopen the q, we're not supposed to post to closed questions.
ASKER
how to do it ?
>>thus it must be prepared for encounter with such apps.
OK, but this makes things trickier. You need to handle *both* streams from the app (i.e. the error stream too) in separate threads and then be prepared to terminate the process yourself as *it* doesn't
OK, but this makes things trickier. You need to handle *both* streams from the app (i.e. the error stream too) in separate threads and then be prepared to terminate the process yourself as *it* doesn't
while(true)
;
you never want to write code like that :)
;
you never want to write code like that :)
> i cant access to the printed "hello" world from process. whu ?
the output is buffered, you'll need to flush the buffer.
And make sure you're not using a buufer on the recieving side either :)
the output is buffered, you'll need to flush the buffer.
And make sure you're not using a buufer on the recieving side either :)
ASKER
ProcessBuilder has an option to redirecting error stream to stdin. its not problem.
> you never want to write code like that :)
its just an example of such an unqualified application. consider any other loop for evers
> you never want to write code like that :)
its just an example of such an unqualified application. consider any other loop for evers
you shouldn't need to use a loop at all to do a wait, waste of CPU
>>ProcessBuilder has an option to redirecting error stream to stdin. its not problem.
Yes, that should get you round that one
Yes, that should get you round that one
ASKER
> the output is buffered, you'll need to flush the buffer.
i said its ok when while(for ever) does not exist i can read output finely. but if the exist, and i destroy the app after a while. the output is not accessible only if the output is less that an amount may be 1024
i said its ok when while(for ever) does not exist i can read output finely. but if the exist, and i destroy the app after a while. the output is not accessible only if the output is less that an amount may be 1024
> if i call process.getExcitCode() i got an InterruptedThreadStateExce ption although the process is not running
have you tried calling waitFor() before getting the exit code.
have you tried calling waitFor() before getting the exit code.
> but if the exist, and i destroy the app after a while. the output is not accessible only if the output is less that an amount may be 1024
yes cause terminating it doesn't give it a chance to flush the buffers and they get lost.
yes cause terminating it doesn't give it a chance to flush the buffers and they get lost.
ASKER
> have you tried calling waitFor() before getting the exit code.
yes i have. it doesn't make any sense. any way i cant grab the output.
yes i have. it doesn't make any sense. any way i cant grab the output.
>>have you tried calling waitFor() before getting the exit code.
You'll be waiting a long time in the case of the above ;-)
You'll be waiting a long time in the case of the above ;-)
ASKER
my prob is not just
while(true)
;
as i said the below is the critical problem
array[6453234] = 0; // out of bound
in this case OS interferes and takes control of execution and then ANY INPUT OPERATION will block.
while(true)
;
as i said the below is the critical problem
array[6453234] = 0; // out of bound
in this case OS interferes and takes control of execution and then ANY INPUT OPERATION will block.
Difficult with a small amount of detail to know what's (not) happening, but you can get into such tight loops that processing anything else becomes difficult
can you use a seperate (native) wrapper application to handle the running of the application and handling of any exceptions, and instead call that app from java. That way you'll have better control of the behaviour of the application that java calls.
ASKER
> use a seperate (native) wrapper application
seems to be the last chance. i also need to run the app as another user to restrict its priviledges. i tried sysinternals PSEXEC but it does not have an option to kill the process after X seconds. i have to write my own RUNAS
seems to be the last chance. i also need to run the app as another user to restrict its priviledges. i tried sysinternals PSEXEC but it does not have an option to kill the process after X seconds. i have to write my own RUNAS
sounds like using a native appo would solve a lot of your problems and give you a lot more control.
Try ProcessKill
Sorry - taskkill
ASKER
yes the answer is native. but how can we call it java ?
trying to call a process to run the app and the after x seconds running another process to kill that app what a nasty what a nasty job , 3 process for each run
trying to call a process to run the app and the after x seconds running another process to kill that app what a nasty what a nasty job , 3 process for each run
Yes - Java is not really designed for such tasks
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/taskkill.mspx?mfr=true
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/taskkill.mspx?mfr=true
why do you need a seperate instance of each for every job? can't you have the manager apps manging more than 1 job?
ASKER
> can't you have the manager apps manging more than 1 job?
which native manager app would do it ? such a big manage is just the OS. and if i want to write my own, i would then re write all the java app in c++
which native manager app would do it ? such a big manage is just the OS. and if i want to write my own, i would then re write all the java app in c++
the java app would certainly have no problem managing multiple processes.
and the native app could possibly avoid starting a new process by calling the c program directly.
what form are the apps to run being delivered?
and the native app could possibly avoid starting a new process by calling the c program directly.
what form are the apps to run being delivered?
ASKER
> what form are the apps to run being delivered?
they are just console applications. read somthing from stdin or a file and calculating the results then output either in a file or stdout.
they are just console applications. read somthing from stdin or a file and calculating the results then output either in a file or stdout.
Try this - it works to some extent for me:
/**
* 30-Mar-2006
*/
package concurrent;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.Execu torService ;
import java.util.concurrent.Execu tors;
import java.util.concurrent.TimeU nit;
/**
* @author Charles
*/
public class RunAndTerminate {
public void startAndStop(long maxRunTimeInSeconds) {
ProcessBuilder pb = new ProcessBuilder();
pb
.command(new String[] { "C:/DOCUME~1/Charles/MYDOC U~1/java/d umpit/loop .exe" });
pb.redirectErrorStream(tru e);
ExecutorService runners = null;
Process p = null;
boolean terminatedNormally = false;
try {
p = pb.start();
runners = Executors.newFixedThreadPo ol(1);
try {
runners.execute(new ProcessHandler(p));
terminatedNormally = runners.awaitTermination(m axRunTimeI nSeconds,
TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.printf("Termina ted normally? - %b\n", terminatedNormally);
// p.destroy(); (Won't work)
if (!terminatedNormally) {
doNativeShutdown();
}
runners.shutdown();
}
}
private void doNativeShutdown() {
try {
ProcessBuilder pb = new ProcessBuilder();
pb.command(new String[] { "taskkill", "/IM", "loop.exe" });
pb.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new RunAndTerminate().startAnd Stop(10L);
System.out.println("All finished!");
}
private class ProcessHandler implements Runnable {
private Process p;
public ProcessHandler(Process p) {
this.p = p;
}
public void run() {
int buf = -1;
InputStreamReader in = null;
try {
in = new InputStreamReader(p.getInp utStream() );
System.out.println("Attemp ting to read process output...");
while ((buf = in.read()) > -1) {
System.out.print((char) buf);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
}
}
}
}
}
/**
* 30-Mar-2006
*/
package concurrent;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.concurrent.Execu
import java.util.concurrent.Execu
import java.util.concurrent.TimeU
/**
* @author Charles
*/
public class RunAndTerminate {
public void startAndStop(long maxRunTimeInSeconds) {
ProcessBuilder pb = new ProcessBuilder();
pb
.command(new String[] { "C:/DOCUME~1/Charles/MYDOC
pb.redirectErrorStream(tru
ExecutorService runners = null;
Process p = null;
boolean terminatedNormally = false;
try {
p = pb.start();
runners = Executors.newFixedThreadPo
try {
runners.execute(new ProcessHandler(p));
terminatedNormally = runners.awaitTermination(m
TimeUnit.SECONDS);
} catch (InterruptedException e) {
e.printStackTrace();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
System.out.printf("Termina
// p.destroy(); (Won't work)
if (!terminatedNormally) {
doNativeShutdown();
}
runners.shutdown();
}
}
private void doNativeShutdown() {
try {
ProcessBuilder pb = new ProcessBuilder();
pb.command(new String[] { "taskkill", "/IM", "loop.exe" });
pb.start();
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
new RunAndTerminate().startAnd
System.out.println("All finished!");
}
private class ProcessHandler implements Runnable {
private Process p;
public ProcessHandler(Process p) {
this.p = p;
}
public void run() {
int buf = -1;
InputStreamReader in = null;
try {
in = new InputStreamReader(p.getInp
System.out.println("Attemp
while ((buf = in.read()) > -1) {
System.out.print((char) buf);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
} catch (IOException e) {
}
}
}
}
}
btw, the native code is the following:
#include <stdio.h>
main() {
printf("%s\n", "Starting...");
for(;;) {
sleep(10);
}
}
#include <stdio.h>
main() {
printf("%s\n", "Starting...");
for(;;) {
sleep(10);
}
}
> printf("%s\n", "Starting...");
try it with:
printf("%s", "Starting...");
plus the multitude of other error conditions that could occur.
Its easy to write something to handle a specific case,. handling *all* cases is the tricky bit.
try it with:
printf("%s", "Starting...");
plus the multitude of other error conditions that could occur.
Its easy to write something to handle a specific case,. handling *all* cases is the tricky bit.