Solved

Java issue - how to force my code to exit when it hangs

Posted on 2013-02-04
7
388 Views
Last Modified: 2013-02-05
I have a Java method that I use for decrypting files by executing the GPG binary and passing in some parameters (see code sample below).

Sometimes for reasons beyond my control, the file that the program is attempting to decrypt is corrupted and cannot be decrypted.  In those cases, I want the program to abort and raise an error.  The problem I am having is that the the program often just hangs and never completes - it is as if it were stuck in an infinite loop.  So rather than trapping the problem and exiting, the program just sits there and never completes.

Is there any way I can force this program so that it will ALWAYS complete - either successfully or by raising an error?

Thanks.



	public static String decryptFile(String gpgBinaryPath, String passphrase,
			 String decryptedFilePath, String encryptedFilePath) {

		//System.out.println("encryptedFilePath: " + encryptedFilePath);
		//System.out.println("decryptedFilePath: " + decryptedFilePath);
		//System.out.println("gpgBinaryPath: " + gpgBinaryPath);
		//System.out.println("passphrase: " + passphrase);
		
		String strExecReturn = "";
		
		String[] cmdArray = new String[] {
				gpgBinaryPath,
				"--no-tty",
				"--yes",
				"-q",
				"-d",
				"--passphrase",
				passphrase,
				"-o",
				decryptedFilePath,
				encryptedFilePath };
		java.lang.Runtime runtime = java.lang.Runtime.getRuntime();
		java.lang.Process ps = null;
		try 
		{
			ps  = runtime.exec(cmdArray);
		} //end try
		catch (IOException e) 
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}//end catch - IOException
		try
		{
			int exitStatus = ps.waitFor();
			//System.out.println ("exit Status = "+exitStatus);
			if(exitStatus!=0)
			{
				InputStream e = ps.getErrorStream();
				String error = "";
				
				BufferedInputStream bre = new BufferedInputStream(e);
				try 
				{
					int readInt = bre.read();
					System.out.println ("readInt = "+readInt);
					while (readInt != -1) 
					{
						char c = (char) readInt;
						error = error + c;
						readInt = bre.read();
					}//end while
				}//end try 
				catch (IOException e1) 
				{
					e1.printStackTrace();
				}//end catch
				
				System.out.println("ERROR_COMMAND "+ error);
				strExecReturn = "ERROR:"+error;
				throw new Exception("Some problem while copying - "+error);
			}//end if
			else if(exitStatus==0)
			{
				strExecReturn = "SUCCESS";
			}//end else if
		}//end try
		catch (java.lang.InterruptedException e) 
		{
			System.out.println("EXCEPTION_TRACE "+ e);
			e.printStackTrace();
		}//end catch - InterruptedException
		catch(Throwable t)
		{
			t.printStackTrace();
		}//end catch - Throwable
		//System.out.println("Hello " + message + " !"); //$NON-NLS-1$ //$NON-NLS-2$
		
		return strExecReturn;
	}//end method - decryptFile

Open in new window

0
Comment
Question by:jbaird123
  • 3
  • 2
  • 2
7 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 38852845
0
 
LVL 26

Accepted Solution

by:
dpearson earned 500 total points
ID: 38853842
The place where you are potentially waiting forever is here:

int exitStatus = ps.waitFor();

I would suggest replacing that with a timeout.  Let's say you're willing to wait for at most 5 minutes before deciding the process has hung and aborting.

You could implement that in a very simple way like this:

Thread.sleep(1000*60*5) ; // Wait 5 mins
int exitStatus = ps.exitValue() ; // Note - this will throw an exception if process has NOT finished (i.e. it's hung)
... now process the output like before

The only downside of this simple approach is you'll always wait 5 mins.  A smarter version would loop, checking the exitValue() every 10 secs or so.  If you get a valid exit code, you process the output.  If you don't get a valid exit code before 5 mins you abort with an error.

Hope that helps,

Doug
0
 

Author Closing Comment

by:jbaird123
ID: 38855634
Thank you, Doug.  This was exactly what I needed.
0
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 86

Expert Comment

by:CEHJ
ID: 38855759
The place where you are potentially waiting forever is here:

int exitStatus = ps.waitFor();

I would suggest replacing that with a timeout.  Let's say you're willing to wait for at most 5 minutes before deciding the process has hung and aborting.
That's not going to help you really. It's far more likely that your app is what is hanging - for the reason given at my link and sublinks. If it's really the process that's hung then it will be down to a bug in GPG
0
 

Author Comment

by:jbaird123
ID: 38855847
CEHJ,

I looked over the information you gave me, but I'm afraid I am still too new to Java to be able to make sense of it all.  

Is it possible to simplify all of that information into a simple call that I can add to my code?

Thanks.
0
 
LVL 26

Expert Comment

by:dpearson
ID: 38857334
CEHJ,

I'm not convinced that it's hanging due to his reading of the error stream.  I think the only place that could happen (if it was an issue with reading the streams) is here:

int readInt = bre.read();

But that shouldn't block when reading an error stream after the process has terminated.  If it did that would be a pretty nasty bug in the JDK wouldn't it?

I think the links you posted are more to solve the problem of how to read the output stream and the error stream while a process is running (a thorny problem).  But that doesn't seem to apply here?

Doug
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 38857384
I don't know what the sequence of events is here. In almost all cases, hanging with Runtime.exec is caused by not consuming process streams in separate threads.

Of course, if the gpg code is problematic when run outside java, then it could be that the process itself is a problem. I didn't get that impression, If that's the case, i missed it
0

Featured Post

3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
JList custom Cell Renderer refresh 15 53
Cipher Configuration on Apache HTTPD 4 53
couple of eclipse 5 25
windows explorer path to command prompt 5 33
After being asked a question last year, I went into one of my moods where I did some research and code just for the fun and learning of it all.  Subsequently, from this journey, I put together this article on "Range Searching Using Visual Basic.NET …
Introduction This article is the first of three articles that explain why and how the Experts Exchange QA Team does test automation for our web site. This article explains our test automation goals. Then rationale is given for the tools we use to a…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
This theoretical tutorial explains exceptions, reasons for exceptions, different categories of exception and exception hierarchy.

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now