Better way to do error handling here?

L

laredotornado

Hi,

I'm using Java 1.5. At a certain point in my program, I have this
code:

phpProcess = Runtime.getRuntime().exec(phpNormalizerCommand);
stdoutReader =
new BufferedReader
(new InputStreamReader(phpProcess.getInputStream()));
stdinWriter =
new PrintWriter
(new OutputStreamWriter(phpProcess.getOutputStream()));

Later I use the stdoutReader and stdinWriter variables. The
"phpNormalizerCommand" variable runs a script that depends on PHP.
However, if PHP is not installed on the machine, the command would
normally print

/usr/bin/php5: bad interpreter: No such file or directory

from a termianl . Is there some way after first ilne of the code above
that I could trap for this error and stop my program if I detect such
an error?

Thanks, - Dave
 
S

Stefan Ram

laredotornado said:
phpProcess = Runtime.getRuntime().exec(phpNormalizerCommand);
from a termianl . Is there some way after first ilne of the code above
that I could trap for this error and stop my program if I detect such
an error?

Usually, the following pattern might work:

try
{ phpProcess = Runtime.getRuntime().exec(phpNormalizerCommand);
if( phpProcess == null )handleNullProcessResult();
else use( phpProcess ); }
catch( final java.lang.Throwable throwable )
{ handle( throwable ); }

After you found the precise type of the error, you should
restrict the catch clause to catch only this.

(I have not looked up the docs and therefore might have
missed something.)
 
I

Ian Shef

(e-mail address removed)-berlin.de (Stefan Ram) wrote in (e-mail address removed)-berlin.de:
Usually, the following pattern might work:

try
{ phpProcess = Runtime.getRuntime().exec(phpNormalizerCommand);
if( phpProcess == null )handleNullProcessResult();
else use( phpProcess ); }
catch( final java.lang.Throwable throwable )
{ handle( throwable ); }

After you found the precise type of the error, you should
restrict the catch clause to catch only this.

(I have not looked up the docs and therefore might have
missed something.)

The javadocs are your friend:

"Starting an operating system process is highly system-dependent. Among the
many things that can go wrong are:

The operating system program file was not found.
Access to the program file was denied.
The working directory does not exist.

In such cases an exception will be thrown. The exact nature of the
exception is system-dependent, but it will always be a subclass of
IOException."

In fact, the javadocs provide this at the begining of the definition for
exec:

public Process exec(String command) throws IOException

The original poster should know this and omitted some important code in the
snippet that was posted.

It might have been simpler to modify phpNormalizerCommand and test the
result than it was to post to the newsgroup.

I tested on WindowsXP using JDK 1.6.0_14 using
the following test program:

package testpack1;
import java.io.IOException;
public class ExecNonExistentProgram {
public static void main(String[] args) {
try {
Runtime.getRuntime().exec("nonexistent");
} catch (IOException e) {
e.printStackTrace();
}
}
}

which generates:

java.io.IOException: Cannot run program "nonexistent": CreateProcess error=
2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
at java.lang.Runtime.exec(Runtime.java:593)
at java.lang.Runtime.exec(Runtime.java:431)
at java.lang.Runtime.exec(Runtime.java:328)
at testpack1.ExecNonExistentProgram.main
(ExecNonExistentProgram.java:15)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot
find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(ProcessImpl.java:81)
at java.lang.ProcessImpl.start(ProcessImpl.java:30)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
... 4 more

which then suggested:

package testpack1;
import java.io.IOException;
public class ExecNonExistentProgram2 {
public static void main(String[] args) {
try {
(new ProcessBuilder("nonexistent")).start() ;
} catch (IOException e) {
e.printStackTrace();
}
}
}

which generates:

java.io.IOException: Cannot run program "nonexistent": CreateProcess error=
2, The system cannot find the file specified
at java.lang.ProcessBuilder.start(ProcessBuilder.java:459)
at testpack1.ExecNonExistentProgram2.main
(ExecNonExistentProgram2.java:6)
Caused by: java.io.IOException: CreateProcess error=2, The system cannot
find the file specified
at java.lang.ProcessImpl.create(Native Method)
at java.lang.ProcessImpl.<init>(ProcessImpl.java:81)
at java.lang.ProcessImpl.start(ProcessImpl.java:30)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:452)
... 1 more
 
J

John B. Matthews

laredotornado said:
I'm using Java 1.5. At a certain point in my program, I have this
code:

phpProcess = Runtime.getRuntime().exec(phpNormalizerCommand);
stdoutReader =
new BufferedReader
(new InputStreamReader(phpProcess.getInputStream()));
stdinWriter =
new PrintWriter
(new OutputStreamWriter(phpProcess.getOutputStream()));

Later I use the stdoutReader and stdinWriter variables. The
"phpNormalizerCommand" variable runs a script that depends on PHP.
However, if PHP is not installed on the machine, the command would
normally print

/usr/bin/php5: bad interpreter: No such file or directory

from a termianl . Is there some way after first ilne of the code above
that I could trap for this error and stop my program if I detect such
an error?

You need to read the Process's error stream via getErrorStream().
ProcessBuilder allows merging stout and sterr, which maybe useful in
this case:

<http://java.sun.com/javase/6/docs/api/java/lang/ProcessBuilder.html>
 
T

Tom Anderson

(e-mail address removed)-berlin.de (Stefan Ram) wrote in (e-mail address removed)-berlin.de:


The javadocs are your friend:

"Starting an operating system process is highly system-dependent. Among the
many things that can go wrong are:

The operating system program file was not found.
Access to the program file was denied.
The working directory does not exist.

In such cases an exception will be thrown. The exact nature of the
exception is system-dependent, but it will always be a subclass of
IOException."

None of those are relevant to this situation.

Here, we know that the script being run exists. But the script specifies
an interpreter which may or may not exist - this is a unix thing which i
think doesn't have an equivalent on windows, but basically, a script can
specify which interpreter should run it on its first line, so you can have
scripts for the shell, perl, python, and PHP all happily coexisting and
being run in the same way. If the specified interpreter doesn't exist, the
script will fail.

I had a quick poke at this on OS X, and what happens in the case of a bad
interpreter is that you get no output on either stream, and an exit code
of 255. If you run the command with "bash -c /path/to/file", then you get
the "bad interpreter" message on the error stream, and an exit status of
126.

You could try something like:

Process proc = Runtime.getRuntime().exec("/path/to/script");
Thread.sleep(100); // long enough for the
try {
int exit = proc.exitValue();
throw new IOException("script died with status " + exit);
}
catch (IllegalThreadStateException e) {
// script has not exited - assume it is now running
}
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(proc.getOutputStream()));
BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream()));
// etc

Although that 100 is very much a magic number.

To be honest, i think your best bet is just to start writing your data to
the script, and catch the broken pipe exception that will happen if the
script craps out.

tom
 
A

Arne Vajhøj

laredotornado said:
I'm using Java 1.5. At a certain point in my program, I have this
code:

phpProcess = Runtime.getRuntime().exec(phpNormalizerCommand);
stdoutReader =
new BufferedReader
(new InputStreamReader(phpProcess.getInputStream()));
stdinWriter =
new PrintWriter
(new OutputStreamWriter(phpProcess.getOutputStream()));

Later I use the stdoutReader and stdinWriter variables. The
"phpNormalizerCommand" variable runs a script that depends on PHP.
However, if PHP is not installed on the machine, the command would
normally print

/usr/bin/php5: bad interpreter: No such file or directory

from a termianl . Is there some way after first ilne of the code above
that I could trap for this error and stop my program if I detect such
an error?

Other have already discussed the funny world of Runtime exec.

But instead of running PHP as an external executable, then you could
consider running the PHP code inside the JVM. Both Caucho and IBM
has created products to allow that.

Arne
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,754
Messages
2,569,522
Members
44,995
Latest member
PinupduzSap

Latest Threads

Top