Handling delayed execution of a program in java - java

I am running an .exe file from my program and it is taking certain time for the same.The output from this command is used in the following statements for further processing. The output is a boolean variable. But the program is returning false immediately, but in fact the command is still in execution and is taking certain time. Because of the false value the subsequent statements is throwing an error. How do i handle this situation.
The return_var = exec(pagecmd) is the executing statement.
boolean return_var = false;
if("true".equals(getConfig("splitmode", ""))){
System.out.println("Inside splitmode if**********************");
String pagecmd = command.replace("%", page);
pagecmd = pagecmd + " -p " + page;
File f = new File(swfFilePath);
System.out.println("The swffile inside splitmode block exists is -----"+f.exists());
System.out.println("The pagecmd is -----"+pagecmd);
if(!f.exists()){
return_var = exec(pagecmd);
System.out.println("The return_var inside splitmode is----"+return_var);
if(return_var) {
strResult=doc;
}else{
strResult = "Error converting document, make sure the conversion tool is installed and that correct user permissions are applied to the SWF Path directory" +
getDocUrl();
}

In conjuction with waitFor() suggested by Andreas, you may also need to use getInputStream of Process object returned by exec() to retrieve the data written by the program you are executing.

Assumed that you are finally using Runtime.exec() inside your exec() method, you can use the waitFor() method of the Process object which is returned from Runtime.exec() to wait until the execution has finished:
...
Process p = Runtime.getRuntime().exec(pagecmd);
int result = p.waitFor();
...
The return value from waitFor() is the exit code of the sub process.
If you actually need to read output from the sub process which the sub process is writing to its stderr or stdout channel, you need to use Process.getInputStream() (Note: not getOutputStream()) and Process.getErrorStream() and read the sub processes output from these streams. Then, check the return values from the stream's read() methods to check if the sub process has terminated (or at least closed its output streams) instead of using waitFor().
Also, for these kind of problems, you should consider using the Apache commons exec library.
Alternatively, you might want to check the ProcessBuilder class.

Related

Create process with method called in Java [duplicate]

Is there a way to start a process in Java? in .Net this is done with for example:
System.Diagnostics.Process.Start("processname");
Is there an equivalent in Java so I can then let the user find the application and then it would work for any OS?
http://www.rgagnon.com/javadetails/java-0014.html
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.file.Paths;
public class CmdExec {
public static void main(String args[]) {
try {
// enter code here
Process p = Runtime.getRuntime().exec(
Paths.get(System.getenv("windir"), "system32", "tree.com /A").toString()
);
// enter code here
try(BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line;
while ((line = input.readLine()) != null) {
System.out.println(line);
}
}
} catch (Exception err) {
err.printStackTrace();
}
}
}
You can get the local path using System properties or a similar approach.
http://download.oracle.com/javase/tutorial/essential/environment/sysprop.html
The Java Class Library represents external processes using the java.lang.Process class. Processes can be spawned using a java.lang.ProcessBuilder:
Process process = new ProcessBuilder("processname").start();
or the older interface exposed by the overloaded exec methods on the java.lang.Runtime class:
Process process = Runtime.getRuntime().exec("processname");
Both of these will code snippets will spawn a new process, which usually executes asynchronously and can be interacted with through the resulting Process object. If you need to check that the process has finished (or wait for it to finish), don't forget to check that the exit value (exit code) returned by process.exitValue() or process.waitFor() is as expected (0 for most programs), since no exception is thrown if the process exits abnormally.
Also note that additional code is often necessary to handle the process's I/O correctly, as described in the documentation for the Process class (emphasis added):
By default, the created subprocess does not have its own terminal or console. All its standard I/O (i.e. stdin, stdout, stderr) operations will be redirected to the parent process, where they can be accessed via the streams obtained using the methods getOutputStream(), getInputStream(), and getErrorStream(). The parent process uses these streams to feed input to and get output from the subprocess. Because some native platforms only provide limited buffer size for standard input and output streams, failure to promptly write the input stream or read the output stream of the subprocess may cause the subprocess to block, or even deadlock.
One way to make sure that I/O is correctly handled and that the exit value indicates success is to use a library like jproc that deals with the intricacies of capturing stdout and stderr, and offers a simple synchronous interface to run external processes:
ProcResult result = new ProcBuilder("processname").run();
jproc is available via maven central:
<dependency>
<groupId>org.buildobjects</groupId>
<artifactId>jproc</artifactId>
<version>2.5.1</version>
</dependency>
See Runtime.exec() and the Process class. In its simplest form:
Process myProcess = Runtime.getRuntime().exec(command);
...
Note that you also need to read the process' output (eg: myProcess.getInputStream()) -- or the process will hang on some systems. This can be highly confusing the first time, and should be included in any introduction to these APIs. See James P.'s response for an example.
You might also want to look into the new ProcessBuilder class, which makes it easier to change environment variables and to invoke subprocesses :
Process myProcess = new ProcessBuilder(command, arg).start();
...

Launch a process with java and then terminate it

Normally I use this code to run a bash script and get it's output
ProcessBuilder pb = new ProcessBuilder("/home/myscript");
Process p = pb.start();
BufferedReader stdInput = new BufferedReader(new InputStreamReader(p.getInputStream()));
String inputRead;
p.waitFor();
while((inputRead=stdInput.readLine()) != null){
Helper.log(inputRead);
}
This works fine but this time the bash script I am using didn't terminate. It's always active and when it detect something it print it. I want to start the script, wait for some time and than check if it detected something.
I tried this code
Thread.sleep(5000);
p.destroy();
String inputRead;
while((inputRead=stdInput.readLine()) != null){
Helper.log(inputRead);
}
But I get as result
java.io.IOException: Stream closed
I also tried
p.waitFor(5, TimeUnit.SECONDS);
while((inputRead=stdInput.readLine()) != null){
Helper.log(inputRead);
}
But the process never ended and I still get the input in the log for ever.
I just want to run the script for a short period of time, in this example 5 seconds and than stop it and get the output generated by the script in this period.
Process.destroy might (and probably will, but this is implementation dependent) kill your process and this is why you're getting your java.io.IOException.
If you're using Java 8, I'd suggest using Process.waitFor with the timeout constructor. You'll be able to check whether your process has hanged or not. If it returns true, you will have captured the process output using normal means. If it returns false, your process might have hanged, so you can either terminate it, or wait some more and try to see if anything has changed.
An alternative would be to control your bash script using the timeout command, so you can be sure that your script will eventually terminate in a finite amount of time.

How to execute a linux terminal command from LUAJ?

I want to simply execute a linux terminal command like ls from LuaJ and the result that it will return or anything that returns i want to receive it and will show the names in the Java Gui. I searched but found this but not one with LuaJ.
Is there any function to execute the terminal command from LuaJ ??
There are multiple ways to do this, for one, you can implement it yourself in Java then link it to LuaJ.
LuaFunction command = new OneArgFunction()
{
public LuaValue call(LuaValue cmd)
{
Process p = Runtime.getRuntime().exec("/bin/sh", "-c", cmd.checkstring());
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
int returnCode = p.waitFor();
return LuaValue.valueOf(returnCode);
}
}
globals.set("command", command);
Then in Lua:
local code = command("ls");
The problem with actually getting the output of a command is that you can't just have a fixall solution. For all the system knows you could be calling a program which runs for 2 hours generating constant output, which could be an issue, not to mention if the program requires input. If you know you're only going to use certain functions you can make a dirty version of above function to capture the output from the stream and return it all instead of the exit code, just don't use it on other processes that don't return quickly. The other alternative is to create a class that wraps the input and output streams from the process and return a coerced version of that class, and manage the input and output from lua.
Lua does have a function that's part of the OsLib called execute(), if execute doesn't exist in your current environment then in Java call:
globals.load(new OsLib());
Before loading the lua code. the os.execute() function returns the status code, and doesn't return the streams, so no way to get the output there. To get around this you can modify the command to pipe the output to a temp file and open it with the io library (new IoLib() if doesn't exist in current environment).
The other option is to use io.openProcess, which also executes the command and returns a file to read the output from.
Resources:
http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/OsLib.html
http://luaj.org/luaj/3.0/api/org/luaj/vm2/lib/IoLib.html

Java: wait for all child process to finish

Environment: Windows 7
I'm launching an external process with ProcessBuilder. This external program can be called with an argument defining how many CPU cores to use. It then launches as many processes to perform the calculation.
The issue seems to be that the initial called process then immediately terminates. So process.waitFor() does not actually wait for the calculation to complete.
How can I make it wait for the child-process it spwaned? Or how can i wait til all process of a specific name have been terminated?
EDIT due to comments:
ProcessBuilder pb = new ProcessBuilder("myExe", "-i", inputFile, "-o", outputFile, "-np", "4");
pb.directory(new File(tempPath));
Process myProcess = pb.start();
myProcess.waitFor();
Process is a 3-rd party exe file (no GUI).
EDIT 2 Possible workaround (which has another issue):
As a workaround I tried a solution found with google:
while(wait) {
Process p = Runtime.getRuntime().exec(System.getenv("windir") +"\\system32\\"+"tasklist.exe /fi \"imagename eq myExe.exe\"");
BufferedReader input = new BufferedReader(new InputStreamReader(p.getInputStream(), "US-ASCII"));
while ((line = input.readLine()) != null) {
if (line.startsWith("INFO: No tasks are running")) {
wait = false;
}
}
if (wait) {
Thread.sleep(2000);
}
input.close();
}
This should return a list of all processes with the given name. Problem is the list is always empty when called from Java but works correctly when called from the cli manually. Any ideas why?
Java-like dirty solution
Currently java.lang.Process is rather poor and is getting enriched.
For example, here you can find the feature requests. In java 8,
you already have methods like isAlive and destroyForcibly So
you can try something like the following dirty solution:
Get the id of the main process by reflection.
Get the child processes - specific for Windows
Wait for the found child processes
Steps 2 and 3 can be implemented as one script and executed as
java.lang.Process.waitFor
Work with the executable
I suppose, that the executable is some kind of MPI program. If you have access to the sources, i'd better change it to work correctly and waiting for all threads.

Java Processbuilder - Catching the exitvalue of another Script?

I try to run a python script in my java programm. What I want to do is to catch the exitValue of the python programm and write it via System.out.println out.
Here is the Python code:
import sys
import subprocess
print "hallo"
i = sys.argv[0]
path = "R:\\xxx\\xxx\\xxx\\read"
resultlist = []
if i == 0:
result = True
else:
result = False
resultlist.append(result)
resultlist.append(path)
sys.exit(resultlist)
The Processbuilder methods .waitFor() and .exitValue() just gives a 0 or a 1 out. So I cant use it.
Is there any possible way to catch the value/string of sys.exit(resultlist) from the python script in my java programm?
man 2 exit:
The function _exit() terminates the calling process "immediately". Any open file descriptors belonging to the process are closed; any children of the process
are inherited by process 1, init, and the process's parent is sent a SIGCHLD signal.
**The value status is returned to the parent process as the process's exit status, and can be collected using one of the wait(2) family of calls.**
You cannot return "complex values" with exit(2) (the syscall) to begin with. If python does that then fine, but it's a "trick". Don't rely on it.
What you want to do is print the output of your program to stdout and capture stdout. For this, use the Process's .getInputStream() and swallow it in, for instance, a ByteArrayOutputStream.
Since you use a ProcessBuilder, you can also use its .redirectOutput() method before executing the process. Since Java 7, it has quite a few options available.

Categories